Top >コンソール・アプリケーション集

プニグマ punigma C言語

#include    <stdio.h>
#include    <conio.h>

/**************************************************
** ローターに対応する構造体
**************************************************/

typedef struct
{
    int wire[26];   // 結線
    int pos;        // 位置
} PUNI_ROTER;

/////////////////////////////////////////////////////////////////////
// ローターの結線を設定する
//  proter: PUNI_ROTER 構造体へのポインタ
//  n1: 結線する端子(0~25)
//  n2: 結線する端子(0~25)
/////////////////////////////////////////////////////////////////////
void Connect(PUNI_ROTER* proter, int n1, int n2)
{
    // n1 を n2 に、n2 を n1 に結線する
    proter->wire[n1] = n2;
    proter->wire[n2] = n1;
}

/////////////////////////////////////////////////////////////////////
// 文字を変換する
//  proter: PUNI_ROTER 構造体へのポインタ
//  ch: 変換する文字
//  return: 変換された文字
/////////////////////////////////////////////////////////////////////
int Encode(PUNI_ROTER* proter, int ch)
{
    int n = (ch - 'A' + proter->pos) % 26;
    int encoded = 'A' + ((proter->wire[n] - proter->pos + 26) % 26);

    proter->pos++;   // ローターを回転

    return encoded;
}

/////////////////////////////////////////////////////////////////////
// プニグマの画面を表示する
//  proter: PUNI_ROTER 構造体へのポインタ
//  input: 入力文字列
//  encoded: 変換後文字列
/////////////////////////////////////////////////////////////////////
void ShowPunigma(const PUNI_ROTER* proter, char* input, char* encoded)
{
    char    str0[] = "-------------------------";
    char    str1[] = "Q W E R T Y U I O P   |||";
    char    str2[] = " A S D F G H J K L    | |";
    char    str3[] = "  Z X C V B N M       |||";

    str2[23] = 'A' + proter->pos;    // ローターの位置を表示

    puts(str0);
    puts(str1);
    puts(str2);
    puts(str3);

    // 入力文字列と変換後文字列を表示
    printf("\n%s    %s\n", input, encoded);
}

/////////////////////////////////////////////////////////////////////
// main
/////////////////////////////////////////////////////////////////////
void main(void)
{
    PUNI_ROTER  roter;          // ローター
    char    input[100] = "";    // 入力文字列
    char    encoded[100] = "";  // 変換後文字列
    int     count = 0;          // 入力文字数を数える
    char*   guide =
        "1~9の数字を入力するとローターが回転します。\n"
        "A~Zを入力すると右側に変換した文字を表示します。\n"
        "0を入力するとプログラムを終了します。";

    // 操作ガイドを表示
    puts(guide);

    // ローターの結線を設定します
    // 0~25が、必ず1回、使用されるようにします
    Connect(&roter, 16, 6);
    Connect(&roter, 15, 20);
    Connect(&roter, 0, 21);
    Connect(&roter, 17, 22);
    Connect(&roter, 7, 2);
    Connect(&roter, 5, 11);
    Connect(&roter, 12, 23);
    Connect(&roter, 10, 1);
    Connect(&roter, 8, 24);
    Connect(&roter, 3, 25);
    Connect(&roter, 18, 9);
    Connect(&roter, 13, 4);
    Connect(&roter, 14, 19);

    // ローターの初期位置を設定
    roter.pos = 0;

    while (count < 99)
    {
        int     ch = 0;     // 入力文字を受け取る変数

        // 画面を表示
        ShowPunigma(&roter, input, encoded);

        // 文字を入力
        ch = _getche();

        // 小文字なら、大文字に変換
        if ('a' <= ch && ch <= 'z')
            ch = ch - 'a' + 'A';

        if ('A' <= ch && ch <= 'Z')
        {
            // A ~ Z の場合
            // 入力文字列と変換後文字列に設定
            input[count] = ch;
            encoded[count] = Encode(&roter, ch);

            count++;

            // 文字列終端の0を代入
            input[count] = 0;
            encoded[count] = 0;
        }
        else if ('1' <= ch && ch <= '9')
        {
            // 1 ~ 9 の場合
            // ローターを回転する
            roter.pos = (roter.pos + ch - '0') % 26;

            count = 0;  // 表示をリセット
        }
        else{
            // 0など、それ以外の場合はプログラムを終了
            break;
        }
    }
}
PAPER BOWL
NEZEN