バックギャモン
初期ファイルの作成
まず、game.h、game.c、test.cの3つのファイルを作成しますが、下図に示すように、
game.hファイル内で、必要なヘッダファイル、定義識別子、関数定義を参照します。他の 2 つのファイルには game.h が含まれています。このファイルは、#include "game.h" だけで十分です。
game.h コードは次のとおりです。
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL]);//棋盘初始化
void DisplayBoard(char board[ROW][COL]);//打印棋盘
void PlayerMove(char board[ROW][COL]);//玩家下棋
void ComputerMove(char board[ROW][COL]);//电脑下棋
char IsWin(char board[ROW][COL]);//判断胜负
このうち、ROW と COL という 2 つの識別子は、チェス盤の行と列のサイズを定義します。これは、関数を作成して使用するときに数値を再利用するのに便利であり、認識性が高く、表現が明確です。
メイン関数ファイル
コードは以下のように表示されます。
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("*****************************************\n");
printf("******** 1.play 0.exit ********\n");
printf("*****************************************\n");
}
void game()
{
char board[ROW][COL] = {
0 };
InitBoard(board);
DisplayBoard(board);
char ret = 0;
while (1)
{
PlayerMove(board);
DisplayBoard(board);
ret = IsWin(board);
if (ret != 'c')
break;
printf("电脑下:\n");
ComputerMove(board);
DisplayBoard(board);
ret = IsWin(board);
if (ret != 'c')
break;
}
if (ret == 'O')
printf("玩家赢!!!\n");
else if(ret == 'X')
printf("电脑赢!!!\n");
else
printf("平局\n");
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while (input);
return 0;
}
具体的なアイデア:
まず、メイン関数を見ていきます。プレイヤーが後でゲーム オプションを選択できるようにするためにプラスチック入力が作成され、その後、乱数のタイム シードが確立されます。これは、後でコンピューターがチェスをプレイする際に使用されます。 . 次の本体は do...while ループです。最初はメニュー メニューです。この関数にはゲーム オプションの出力が含まれており、次の scanf はプレーヤーのゲーム オプションの入力を記録するために使用されます。ステートメントは switch ステートメントによって判断されます。ゲームを開始するには 1 を入力します。ゲームを終了するには 0 を入力します。ゲームを終了するには、other を入力します。ゲーム関数をもう一度見てみましょう。最初にチェス盤を作成します (本質は 2 次元です)。配列)、値のデフォルトは 0 です。ここでチェスをプレイするとき、ボード上に何を配置するか、ボードのタイプが定義されることに注意してください。たとえば、ここでは文字を配置し、次に char タイプを使用し、その後初期化します。 、初期化後、配列はスペースで埋められ、チェス盤を印刷し、結果を判断するための情報を受け取るために使用される文字タイプ ret を作成します。その後、マンマシンチェスのループについて、結果がない限り、勝ち負けでループし続けます。その後、プレイヤーはチェスをし、印刷します。このとき判定があります。ここでの「c」は判定関数の継続情報です。プレイを継続するための条件が満たされていない場合、飛び出します。コンピューターも同じです。最後の段落は勝者の判断です。受け取った戻り値が「O」の場合、プレーヤーの勝ちです。値が 'X' ' の場合、コンピューターが勝ちます。それ以外の場合は引き分けです。具体的な実装については、次の関数の構造を参照してください。
チェス盤の初期化 (InitBoard)
ここから、次のすべての関数が
次のように game.c ファイル コードに含まれます。
void InitBoard(char board[ROW][COL])
{
int i = 0;
for (i = 0; i < ROW; i++)
{
int j = 0;
for (j = 0; j < COL; j++)
{
board[i][j] = ' ';
}
}
}
具体的なアイデア:
ここでは 2 つのループを使用して、チェス盤内のすべての要素をスペースに初期化します。
チェス盤を印刷する (DisplayBoard)
コードは以下のように表示されます。
void DisplayBoard(char board[ROW][COL])
{
int i = 0;
for (i = 0; i < ROW; i++)
{
int j = 0;
for (j = 0; j < COL; j++)
{
printf(" %c ", board[i][j]);
if (j < ROW - 1)
printf("|");
}
printf("\n");
if(i < ROW - 1)
{
for (j = 0; j < COL; j++)
{
printf("---");
if (j < COL - 1)
printf("|");
}
printf("\n");
}
}
}
具体的なアイデア:
まず、下の図を見てみましょう。チェス盤の効果を印刷するために
、チェス盤を 2 種類に分割し、行ごとに印刷します。上記の書き込み方法は、必要に応じてチェス盤のサイズを変更できます関数を変更せずに、最初の行にはスペースピースと垂直バーが含まれており、合計 3 つあり、最後の行には垂直バーがないので、最初の線種の印刷サイクルが書き出されていることを確認してください。 2 行目には 3 つの水平バーと 1 つの垂直バー Bar が含まれていますが、最後の行は追加されません。また、最後の行ではこれが印刷されないことに注意してください。そのため、印刷全体の原則である 2 番目の行タイプの印刷サイクルも書き込まれます。サイクルはこんな感じ
プレイヤーの動き (PlayerMove)
コードは以下のように表示されます。
void PlayerMove(char board[ROW][COL])
{
int x = 0, y = 0;
printf("玩家下棋:>\n");
while (1)
{
printf("请输入下棋坐标,中间用空格隔开:>");
scanf("%d%d", &x, &y);
if(x>=1&&x<=3&&y>=1&&y<=3)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = 'O';
break;
}
else
printf("此处被占用,请重新落子\n");
}
else
{
printf("坐标非法,请重新落子\n");
}
}
}
具体的なアイデア:
まず、プレイヤーが配置したい座標を受け取る 2 つの xy 変数を作成します。ここでの while ループは、プレイヤーが間違った座標を入力するのを防ぐために確立されています。入力が正しければ、ループから抜け出します。 . ここでの判定条件はランクによる 1~3 の基準なので、正しい位置を見つけるには 2 次元配列から 1 を引く必要があります. 以下の判定条件はボールを配置するために空です. 占有されている場合、または不正な座標を入力すると、サイクルに戻り、座標が入力されます。プレイヤーの動きは文字「O」です。
図に示すように:
コンピュータの移動
コードは以下のように表示されます。
void ComputerMove(char board[ROW][COL])
{
while (1)
{
int x = rand()%ROW, y = rand()%COL;
if (board[x][y] == ' ')
{
board[x][y] = 'X';
break;
}
}
}
具体的なアイデア:
ここでは時間をシードとした乱数を使用し、行と列をモデルにして 0 ~ 2 の乱数値を取得し、判定条件も空でない場合はドロップします。コンピューターは文字 X を動かします。
図に示すように:
結果を決める
コードは以下のように表示されます。
char IsWin(char board[ROW][COL])
{
int i = 0;
for (i = 0; i < ROW; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')//行
{
return board[i][0];
}
}
for (i = 0; i < COL; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')//列
{
return board[0][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')//对边
return board[0][0];
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')//对边
return board[0][2];
if (IsFull(board) == 1)
return 'q';
return 'c';
}
具体的な考え方:
3 枚駒チェスの結果は同列、同列、同対角の 3 つの状況しかないので、それに応じて待ちたいと判断する条件文を書き、が空ではない場合は、条件のいずれかを返します。要素は 1 つだけです。最後にボードがいっぱいかどうかを判断し、ボードがいっぱいの場合は任意の値 ('c' に等しくない、'c' が続行の条件) を返し、最終的に上記の条件が満たされない場合は続行します。ボードがいっぱいかどうかを判断するための
別の関数コードを次に示します。
int IsFull(char board[ROW][COL])
{
int i = 0,j = 0;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
2次元配列のトラバーサルマッチングで、空の位置がある場合は0を返し、一致しない場合は1を返します。
結果は図のように判定され、
引き分け
プレイヤーが勝ち、
コンピュータが勝ちになります
。乱数のおかげで、実際に勝つのは非常に簡単ですが、負けるのは非常に難しいため、このコードの最終的な目標を達成することはできません。ゲームはコンピュータに勝たせることです(手動で面白い)
すべてのコード
ゲーム.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL]);
void DisplayBoard(char board[ROW][COL]);
void PlayerMove(char board[ROW][COL]);
void ComputerMove(char board[ROW][COL]);
char IsWin(char board[ROW][COL]);
ゲーム.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char board[ROW][COL])
{
int i = 0;
for (i = 0; i < ROW; i++)
{
int j = 0;
for (j = 0; j < COL; j++)
{
board[i][j] = ' ';
}
}
}
void DisplayBoard(char board[ROW][COL])
{
int i = 0;
for (i = 0; i < ROW; i++)
{
int j = 0;
for (j = 0; j < COL; j++)
{
printf(" %c ", board[i][j]);
if (j < ROW - 1)
printf("|");
}
printf("\n");
if(i < ROW - 1)
{
for (j = 0; j < COL; j++)
{
printf("---");
if (j < COL - 1)
printf("|");
}
printf("\n");
}
}
}
void PlayerMove(char board[ROW][COL])
{
int x = 0, y = 0;
printf("玩家下棋:>\n");
while (1)
{
printf("请输入下棋坐标,中间用空格隔开:>");
scanf("%d%d", &x, &y);
if(x>=1&&x<=3&&y>=1&&y<=3)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = 'O';
break;
}
else
printf("此处被占用,请重新落子\n");
}
else
{
printf("坐标非法,请重新落子\n");
}
}
}
void ComputerMove(char board[ROW][COL])
{
while (1)
{
int x = rand()%ROW, y = rand()%COL;
if (board[x][y] == ' ')
{
board[x][y] = 'X';
break;
}
}
}
int IsFull(char board[ROW][COL])
{
int i = 0,j = 0;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char IsWin(char board[ROW][COL])
{
int i = 0;
for (i = 0; i < ROW; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
{
return board[i][0];
}
}
for (i = 0; i < COL; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
return board[0][0];
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
return board[0][2];
if (IsFull(board) == 1)
return 'q';
return 'c';
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("*****************************************\n");
printf("******** 1.play 0.exit ********\n");
printf("*****************************************\n");
}
void game()
{
char board[ROW][COL] = {
0 };
InitBoard(board);
DisplayBoard(board);
char ret = 0;
while (1)
{
PlayerMove(board);
DisplayBoard(board);
ret = IsWin(board);
if (ret != 'c')
break;
printf("电脑下:\n");
ComputerMove(board);
DisplayBoard(board);
ret = IsWin(board);
if (ret != 'c')
break;
}
if (ret == 'O')
printf("玩家赢!!!\n");
else if(ret == 'X')
printf("电脑赢!!!\n");
else
printf("平局\n");
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while (input);
return 0;
}
エピローグ
最近C言語ブログがたくさん更新されていますので、皆さんも応援していただければ幸いです!!!
興味のある友達は作者に注目してください、内容が良いと思うなら、ワンクリックトリプルリンクをお願いします、カニカニ!!!
作るのは簡単ではありません、不正確な点があればご指摘ください
ご訪問ありがとうございます、UUの視聴が私が頑張れるモチベーションになっています
時間をきっかけに、お互いより良い人間になりましょう!!!