バックギャモン (3 チェス) (C 言語版)

您所在的位置:网站首页 errorloadingmedia是什么意思 バックギャモン (3 チェス) (C 言語版)

バックギャモン (3 チェス) (C 言語版)

2023-04-12 10:33| 来源: 网络整理| 查看: 265

一夜にして成功することはありません。

ここに画像の説明を挿入

目次

1. バックギャモンの紹介

2. 設計思想

3. コードの実装

3.1 初期化

3.2 チェス盤を印刷する

 3.3 プレイヤーがチェスをする

 3.4 コンピューターチェス

 3.5 条件判定

3.5.1 変数の定義

3.5.2 右斜め判定

3.5.3 左斜め判定

3.5.4 行と列の決定

 4.組み合わせ

5. ソースコード

6. まとめ

1. バックギャモンの紹介

バックギャモンはリバーシの一種です。バックギャモンは伝統的な民俗ゲームで、九公チェス、サークルチャチャ、ワンドラゴン、チックタックトーなどとも呼ばれます。正方形の対角線を結び、反対側に 3 つのポーンを順番に配置し、3 つのポーンを一列に並べると、相手は負けます。ただし、引き分けになることも多々あります。一般的な三月チェスを図に示します

 3 バンチェスのルールを理解したら、C 言語で実装する方法を設計しましょう。ソフトウェア工学設計のモジュール化の考え方を取り入れており、機能を一つ一つ設計していくと、最終的にパッケージ化されます。そのため、最後にアプレット メニューを設計します。このコードプログラミングソフトウェアは Vs2022 を使用しています。

2. 設計思想

チェスをしたいなら、チェス盤が必要なので、まずチェス盤を印刷します。チェスをしていると、プレイした「チェスの駒」を保存する何かが必要になります.このチェス盤を見たとき、最初に思い浮かぶのは 2 次元配列です。チェス盤とデータを格納する 2 次元配列が用意できたら、次のステップは自分とコンピューターでチェスをすることです。チェスの次のゲームが終了するたびに、ゲームに勝つための条件が満たされているかどうかを判断する必要があり、どちらの側が条件を満たしていれば、ゲームは終了し、パーティーが勝ちます。チェス盤がいっぱいで勝者がいない場合、引き分けが出力されます。

要約すると、次の関数を C 言語で実装する必要があります。

1. チェス盤の機能を印刷する

2.プレイヤーチェス機能

3.コンピュータチェス機能

4. 判定機能

3. コードの実装 3.1 初期化

まず、データを保存するために 2 次元配列を定義し、2 次元配列を初期化します。 

char arr[Row][Col] = { 0 }; init_chess(arr); //初始化

注: ここでの Row と Col はそれぞれチェス盤の行と列です. この定義はチェス盤を修正するのに便利です. N チェスを実現するには素晴らしい場所です.

#define Row 3 #define Col 3

初期化関数コード:

void init_chess(char arr[Row][Col]) // 初始化棋盘 { int i = 0; int j = 0; for (i = 0; i < Row; i++) { for (j = 0; j < Col; j++) { arr[i][j] = ' '; } } }

2 次元配列を初期化するには、ネストされた 2 つの for ループを介して 2 次元配列の各セルをトラバースし、スペースとして初期化します。 

3.2 チェス盤を印刷する

初期化が完了したら、チェス盤の印刷を正式に開始します。まず、印刷されたチェス盤を見てみましょう。

チェス盤を印刷する関数コードを最初に置きます。

void input_chess(char arr[Row][Col]) //打印棋盘 { int i = 0; int j = 0; for (i = 0; i < Row; i++) { for (j = 0; j < Col; j++) { printf(" %c ", arr[i][j]); if (j != Col - 1) { printf("|"); } } printf("\n"); if (i != Row - 1) { for (j = 0; j < Col; j++) { printf("---"); if (j != Col - 1) { printf("|"); } } printf("\n"); } } }

 次に、コードを段階的に分析します. 下の図に示すように、ネストされた 2 つの for ループがトラバースし、2 次元配列を出力します. 出力形式は space , arr[i][j], space であることに注意してください. スペースはより良い観察のためのものです。

 次のコードの意味は、各行の最後の列が印刷されるたびに、「|」  分割線を印刷する必要がないということです。これも、印刷したチェス盤に基づいて理解しやすいです。最後の行が印刷された後に改行が印刷されます。

if (j != Col - 1) { printf("|"); }

 バックギャモンボードの印刷に限らず、n-moonチェスボードの印刷も実現できることは特筆に値する.ここでは定義で定義されたRowとColの2つのランクの利点も反映されている. .

 3.3 プレイヤーがチェスをする

 次のステップは、チェスをプレイする機能を実現することです. それはまだ同じです. 最初にコードを入れてから、それを段階的に分析しましょう.

 プレーヤーのチェス機能コード:

void player_chess(char arr[Row][Col]) //玩家下棋 { int i = 0; int j = 0; while (1) { printf("你下:\n"); scanf("%d %d", &i, &j); if (i > 0 && i 0 && j Col ? Col : Row; int flag = 0; int sum1 = 0; int sum2 = 0; int sum3 = 0; int sum4 = 0; j = Col - 1; while (i < Row && j >= 0) { if (arr[i][j] == '*') { sum1++; if (sum1 == num) { return '*'; } } if (arr[i][j] == '#') { sum2++; if (sum2 == num) { return '#'; } } i++; j--; } // sum1 = 0; sum2 = 0; for (i = 0; i < (Row > Col ? Col : Row); i++) { if (arr[i][i] == '*') { sum1++; if (sum1 == num) { return '*'; } } if (arr[i][i] == '#') { sum2++; if (sum2 == num) { return '#'; } } } for (i = 0; i < Row; i++) { sum1 = 0; sum2 = 0; sum3 = 0; sum4 = 0; for (j = 0; j < Col; j++) { if (arr[i][j] == ' ') { flag = 1; } //列 if (arr[i][j] == '*') { sum1++; if (sum1 == num) { return '*'; } } if (arr[i][j] == '#') { sum2++; if (sum2 == num) { return '#'; } } //行 if (arr[j][i] == '*') { sum3++; if (sum3 == num) { return '*'; } } if (arr[j][i] == '#') { sum4++; if (sum4 == num) { return '#'; } } } } if (flag == 0) { return '@'; } return '1'; }

 次に、段階的な分析に進みます。

3.5.1 変数の定義

 ここでの数値は行と列の小さい方の数値を記録し、その後の条件判断に便利です。

3.5.2 右斜め判定

 このサイクルでは、チェス盤の右対角線が連続していると判断します. 図に示すように、Col-1 の値を j に割り当てます.ここで、i は行を表し、j は列を表します. i=0が同時に成立した場合、ループに入る。sum1 と sum2 を使用して、プレイヤーのチェスの駒の数とコンピューターのチェスの駒の数をそれぞれカウントします。そして、判断する if 文が続き、プレイヤーのチェスの駒の数が指定されたチェスの勝利数に達した場合、 return は * を返し、コンピューターのチェスの駒の数が指定された勝利のチェスの数に達した場合、 return は# を返します。 、いずれにも達しない場合は、i++、j-- を続行し、return return 条件が満たされ、ループが返されるまで、または while ループ条件が満たされない場合、ループが飛び出します。

3.5.3 左斜め判定

 このサイクルで判断するのは、図のようにチェス盤の左の対角線です。右対角線の判定と同様に、今度は for ループを使い、同じく sum1 と sum2 を使ってプレイヤーとコンピュータのチェスの駒の数をそれぞれ記録し、if 文で判定します。チェスの駒が指定された勝利チェスの駒の数に達した場合、対応するプレイヤーのチェスの駒を返します。それ以外の場合は、ループから抜けるまでループを実行し続けます。

3.5.4 行と列の決定

 この判定では、最初のif文で盤面にスペースがあるかどうかを判定し、盤面にスペースがあればフラグを1にセットします。6 番目の if文に対応して、フラグが 0、つまりボードにスペースがなく、前の判定条件を満たさない場合は、@ を返して引き分けを示します。2 番目の ifと3 番目の ifステートメントは、各行を判断し、sum1 を使用してプレーヤーのピースの数をカウントし、sum2 を使用してコンピューターのピースの数をカウントし、指定された数の入賞ピースに達したときに対応するシンボルを返すことを示しています。4 番目の ifと5 番目の ifステートメントは、各列を判断し、sum3 を使用してプレーヤーのピースの数をカウントし、sum4 を使用してコンピューターのピースの数をカウントし、対応するピースの数に達したときに対応するシンボルを返すことを示しています。

 4.組み合わせ

 すべての機能モジュールが完成したら、最終的な組み合わせを作成するだけです。1 つ目は、メニューを印刷することです。メニュー関数を使用して、メニューを印刷します。

 メニュー機能:

void menu() { printf("~~~~~~~~~~~~~~~~~~~~~~~~~\n"); printf("~~~~~~~~~1.start~~~~~~~~~\n"); printf("~~~~~~~~~0.exit ~~~~~~~~~\n"); printf("~~~~~~~~~~~~~~~~~~~~~~~~~\n"); }

メニューが印刷された後、メイン関数でメニュー関数を呼び出し、対応するテキストプロンプト情報を出力し、ユーザーに選択入力をさせて変数 i に割り当て、switch ステートメントを使用して選択を行います。 、ユーザーが間違いを犯したり、連続してプレイしたい場合があるため、ゲームは繰り返し入力する必要があるため、ここで while(i) ループを使用します。ユーザーがプログラムを終了して 0、i = 0 を入力したい場合にのみ、ループが終了します。プログラムは終了します。

int main() { int i = 1; srand((unsigned int)time(NULL)); while (i) { menu(); printf("请输入你的选择\n"); scanf("%d", &i); switch (i) { case 1: game(); break; case 0: printf("成功退出!\n"); break; default: printf("输入错误,请重新输入\n"); break; } } return 0; }

次に、ゲームをプレイするためのゲーム関数があります. チェス盤の初期化と印刷の後, チェスのプレイを開始します. チェスのプレイはサイクルプロセスの繰り返しであるため, ここでは while(1) サイクルが使用されます. 結果が出てきて、ループから抜け出します。ここでは ch で判定関数の戻り値を受け取り、戻り値が*の場合はプレイヤーの勝利を意味し、対応する情報を出力してゲームを終了します。戻り値が#の場合は、コンピュータが勝利したことを意味し、対応する情報を出力してゲームを終了します。戻り値が@の場合は引き分けを意味し、対応する情報を出力してゲームを終了します。戻り値が'1'の場合、結果がなく、チェスを続行することを意味します。

ここでは、プログラムの小さな最適化も行いました。i、j、val 変数を定義し、i を使用してプレイヤーがチェスをプレイした回数をカウントし、j を使用してコンピューターがチェスをプレイした回数をカウントし、val をカウントします。チェスの勝数が指定されていて、チェスの手番が指定されていない場合、指定されたチェスの勝数に達すると、判定を行う必要がなくなり、判定の時間を節約できます。

void game() { int i = 0; int j = 0; char ch = 0; int val = Row > Col ? Col : Row; char arr[Row][Col] = { 0 }; init_chess(arr); //初始化 input_chess(arr); //打印 while (1) { player_chess(arr); //玩家下 i++; if (i >= val) { ch = think_chess(arr); if (ch == '*') { printf("玩家赢\n"); break; } if (ch == '#') { printf("电脑赢\n"); break; } if (ch == '@') { printf("平局\n"); break; } } computer_chess(arr); // 电脑下 j++; if (j >= val) { ch = think_chess(arr); if (ch == '*') { printf("玩家赢\n"); break; } if (ch == '#') { printf("电脑赢\n"); break; } if (ch == '@') { printf("平局\n"); break; } } } } 5. ソースコード

このプログラミングは、head.h、test.c、chess.c の 3 つのファイルに分かれています。head.h はヘッダー ファイルと関数宣言を格納するために使用され、test.c はテスト用の主要な関数を格納するために使用され、chess.c は関数モジュール コードを格納するために使用され、以下は 3 つのファイルのソース コードです。

head.h

#define _CRT_SECURE_NO_WARNINGS 1 #define Row 3 #define Col 3 #include #include #include void init_chess(char arr[Row][Col]); //初始化 void input_chess(char arr[Row][Col]); //打印棋盘 void player_chess(char arr[Row][Col]); //玩家下 void computer_chess(char arr[Row][Col]); //电脑下 char think_chess(char arr[Row][Col]); //判输赢

test.c

#define _CRT_SECURE_NO_WARNINGS 1 #include "head.h" void game() { int i = 0; int j = 0; char ch = 0; int val = Row > Col ? Col : Row; char arr[Row][Col] = { 0 }; init_chess(arr); //初始化 input_chess(arr); //打印 while (1) { player_chess(arr); //玩家下 i++; if (i >= val) { ch = think_chess(arr); if (ch == '*') { printf("玩家赢\n"); break; } if (ch == '#') { printf("电脑赢\n"); break; } if (ch == '@') { printf("平局\n"); break; } } computer_chess(arr); // 电脑下 j++; if (j >= val) { ch = think_chess(arr); if (ch == '*') { printf("玩家赢\n"); break; } if (ch == '#') { printf("电脑赢\n"); break; } if (ch == '@') { printf("平局\n"); break; } } } } void menu() { printf("~~~~~~~~~~~~~~~~~~~~~~~~~\n"); printf("~~~~~~~~~1.start~~~~~~~~~\n"); printf("~~~~~~~~~0.exit ~~~~~~~~~\n"); printf("~~~~~~~~~~~~~~~~~~~~~~~~~\n"); } int main() { int i = 1; srand((unsigned int)time(NULL)); while (i) { menu(); printf("请输入你的选择\n"); scanf("%d", &i); switch (i) { case 1: game(); break; case 0: printf("成功退出!\n"); break; default: printf("输入错误,请重新输入\n"); break; } } return 0; }

チェス c

#pragma once #include "head.h" void init_chess(char arr[Row][Col]) // 初始化棋盘 { int i = 0; int j = 0; for (i = 0; i < Row; i++) { for (j = 0; j < Col; j++) { arr[i][j] = ' '; } } } void input_chess(char arr[Row][Col]) //打印棋盘 { int i = 0; int j = 0; for (i = 0; i < Row; i++) { for (j = 0; j < Col; j++) { printf(" %c ", arr[i][j]); if (j != Col - 1) { printf("|"); } } printf("\n"); if (i != Row - 1) { for (j = 0; j < Col; j++) { printf("---"); if (j != Col - 1) { printf("|"); } } printf("\n"); } } } void player_chess(char arr[Row][Col]) //玩家下棋 { int i = 0; int j = 0; while (1) { printf("你下:\n"); scanf("%d %d", &i, &j); if (i > 0 && i 0 && j Col ? Col : Row; int flag = 0; int sum1 = 0; int sum2 = 0; int sum3 = 0; int sum4 = 0; j = Col - 1; while (i < Row && j >= 0) { if (arr[i][j] == '*') { sum1++; if (sum1 == num) { return '*'; } } if (arr[i][j] == '#') { sum2++; if (sum2 == num) { return '#'; } } i++; j--; } // sum1 = 0; sum2 = 0; for (i = 0; i < num; i++) { if (arr[i][i] == '*') { sum1++; if (sum1 == num) { return '*'; } } if (arr[i][i] == '#') { sum2++; if (sum2 == num) { return '#'; } } } for (i = 0; i < Row; i++) { sum1 = 0; sum2 = 0; sum3 = 0; sum4 = 0; for (j = 0; j < Col; j++) { if (arr[i][j] == ' ') { flag = 1; } //行 if (arr[i][j] == '*') { sum1++; if (sum1 == num) { return '*'; } } if (arr[i][j] == '#') { sum2++; if (sum2 == num) { return '#'; } } //列 if (arr[j][i] == '*') { sum3++; if (sum3 == num) { return '*'; } } if (arr[j][i] == '#') { sum4++; if (sum4 == num) { return '#'; } } } } if (flag == 0) { return '@'; } return '1'; }

今回はコードもgiteeにアップロードしてありますが、自分でgiteeからコードをダウンロードすることもできます

test_7_28 Sanbang·Niu おじいちゃんはコードを書くのが大好きで、ゴミを勉強します- Code Cloud- Open Source China (gitee.com)

6. まとめ

 今回はコードの一部に不備があり、まだ最適化できる場所がたくさんあります. 時間の関係で、これを最初に書き、後で修正して、より優れたコードを読者に提供できるように努めます.この記事では私の個人的なことを紹介します 作者自身が表現が下手で、本来言いたかったことを言いきれないところがまだまだあると感じますので、言葉があれば意味を伝えていない記事では, 読者がもっと含めてくれることを願っています. コメント欄で質問したり、著者にコメントや提案を提供したりできます. 著者自身も、読者の皆様から寄せられたご意見・ご要望を真摯に受け止め、より優れた価値のある記事をお届けできるよう、改善に努めてまいります。コードに不備がある場合は、コメント欄で指摘していただけると幸いです. 議論と評価を歓迎します.

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3