[Bangqi] Not just backgammon, but also backgammon and backgammon.

Table of contents

One: code implementation

Two: Some examples in the code illustrate


One: code implementation

There are the following three files, two source files, and one header file

---test.c

---game.h

---game.c

The first source file test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"
//打印的棋盘样式
// 两种棋盘的样式,我开始没有找到“-”这个短横,用了“_”这个短横,设计了很久第一个样式唉唉唉,不辜负我花的时间,我决定都打印出来
// 都可以我觉得,不影响(编译出来不是斜杠啊啊啊,这里给显示成斜杠了)
//   |   |    
//___|___|___
//   |   |
//___|___|___
//   |   |
//___|___|___

//   |   |   
//---|---|---
//   |   |   
//---|---|---
//   |   |   
void menu()
{
	printf("*********************************\n");
	printf("********1.play     0.end*********\n");
	printf("*********************************\n");
}
void game()
{
	char arr[ROW][COL];//建立一个数组,用于存储用户和电脑的棋子
	Initboard(arr, ROW, COL);//调用函数,初始化数组,使打印出来的空盘有规则,美观
	Printboard(arr, ROW, COL);//调用函数,打印空盘,供玩家看到棋盘
	char ret = 0;//初始化一个字符变量,用于控制游戏是否继续
					//1. 玩家赢了 - *
					//2. 电脑赢了 - #
					//3. 平局 - Q
					//4. 游戏继续 - C
	while (1)//游戏整体的逻辑
	{
		Playermove(arr, ROW, COL);//调用函数,玩家走
		Printboard(arr, ROW, COL);//调用函数,打印出玩家走后的棋盘
		ret = Iswin(arr, ROW, COL);//判断玩家是否赢得游戏
		if (ret != 'C')//没赢,没输,而且棋盘没满(平局),游戏继续
		{
			break;
		}
		Computermove(arr, ROW, COL);//调用函数,电脑走
		Printboard(arr, ROW, COL);//调用函数,打印电脑走后的棋盘
		ret = Iswin(arr, ROW, COL);//判断电脑是否赢得游戏
		if (ret != 'C')//没赢,没输,而且棋盘没满(平局),游戏继续
		{
			break;
		}
	}
	//根据函数的返回值打印游戏的输赢
	if (ret == '*')
	{
		printf("恭喜你,你赢了\n");
	}
	if (ret == '#')
	{
		printf("很遗憾,你输了\n");
	}
	if (ret == 'Q')
	{
		printf("哎呦,平局啦\n");
	}
}
//用户进行选择是否开始游戏
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));//播下一个种子,使电脑走的位置是随机的
	do
	{
		menu();
		printf("请选择:>");
		scanf_s("%d", &input);
		switch (input)
		{
		case 1:
			printf("开始游戏\n");
			game();
			break;
		case 0:
			printf("结束游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
		return 0;
}

The header file game.h to be referenced

#pragma once
//定义棋盘的大小,方便以后直接更改棋盘大小,否则,要改一大堆
#define ROW 3
#define COL 3
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void Initboard(char arr[ROW][COL], int row, int col);
void Printboard(char arr[ROW][COL], int row, int col);
void Playermove(char arr[ROW][COL], int row, int col);
void Computermove(char arr[ROW][COL], int row, int col);
char Iswin(char arr[ROW][COL], int row, int col);
char Isfull(char arr[ROW][COL], int row, int col);
//int Isqual(char z);这个我没用上,找到了其他方法替代,这是我的思考过程,就不删掉了

The second source file, game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void Initboard(char arr[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0;j < col; j++)
		{
			arr[i][j] = ' ';
		}
	}
}
//第一个棋盘样式
//   |   |    
//___|___|___
//   |   |
//___|___|___
//   |   |
//___|___|___

//void Printboard(char arr[ROW][COL], int row, int 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");
//		for (j = 0; j < COL; j++)
//		{			
//			printf("___");
//			if (j < COL - 1)
//				printf("|");
//		}
//		printf("\n");
//	}
//}
//第二个棋盘样式
//   |   |   
//---|---|---
//   |   |   
//---|---|---
//   |   |   
void Printboard(char arr[ROW][COL], int row, int 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");
		for (j = 0; j < COL; j++)
		{
			if (i < ROW - 1)
			{
				printf("---");
				if (j < COL - 1)
					printf("|");
			}
		}
		if(i<row-1)
		printf("\n");
	}
}
void Playermove(char arr[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	int p = 1;
	printf("请输入你要放入的位置:");
	while (p)
	{
		scanf_s("%d %d", &x, &y);
		if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
		{
			if (arr[x - 1][y - 1] == ' ')
			{
				arr[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("输入错误,请重新输入:");
			}
		}
		else 
		{
			printf("输入错误,请重新输入:");
		}
	}
}
void Computermove(char arr[ROW][COL], int row, int col)
{

	int p = 1;
	printf("电脑走:>\n");
	while (p)
	{
		int x = 0;
		int y = 0;
		x = rand() % row+1;
		y = rand() % col+1;
		if (arr[x - 1][y - 1] == ' ')
		{
			arr[x - 1][y - 1] = '#';
			break;
		}
	}
}
//判断是否赢,逻辑我也想了好久啊啊啊,一直修bug
//没有按照b站老师三子棋盘固定的判断输赢,而是n子棋都可以
//一共有四种赢的情况,对角线按两种
//第一种:判断行是否一样
//第二种,判断列是否一样
//第三种,判断下标一样的对角线,是否一样
//第四种,判断下标不一样的对角线,是否一样
//其中,第四种下标不一样有什么规则呢,分析一下,不难看出,行列下标之和为数组大小(就是这里的row,或col)-1
char Iswin(char arr[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	int count1 = 0;
	int count2 = 0;
	int count3 = 0;
	int count4 = 0;
	char z1 = 0;
	char z2 = 0;
	char z3 = 0;
	char z4 = 0;
	int q1 = -1;
	int q2 = -1;
	//for (i=0;i<row;i++)
	//{
	//	if (arr[i][0] == arr[i][1] && arr[i][0] == arr[i][2] && arr[i][0] != ' ')
	//	{
	//		return arr[i][0];
	//	}
	//}
	//for (j = 0; j < col; j++)
	//{
	//	if (arr[0][j] == arr[1][j] && arr[0][j] == arr[2][j] && arr[0][j] != ' ')
	//	{
	//		return arr[0][j];
	//	}
	//}
//第一种:判断行是否一样
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col-1; j++)
		{
			if (arr[i][j] == arr[i][j + 1]&& arr[i][j]!=' ')
			{
				if (arr[i][j] == z1 || z1 == 0)//其中这里的逻辑是为了确保两两比较时,使count1++多执行的情况发生,可以看一下博客里的例子,下面列和对角线的逻辑也一样
				{
					if (q1 == i || q1 == -1)//这个逻辑也是为了防止不同行是,也能进入使count1++执行,下面列的也一样
					{
						count1++;
						z1 = arr[i][j];
						q1 = i;
					}
				}
				if (count1 == row - 1)
				{
					return arr[i][j];
				}
			}
			else
			{
				break;
			}
		}
	}
	//第二种,判断列是否一样
	for (j = 0; j < col; j++)
	{
		for (i = 0; i < row - 1; i++)
		{
			if (arr[i][j] == arr[i+1][j] && arr[i][j] != ' ')
			{
				if(arr[i][j] == z2 || z2 == 0)
				{
					if (q2 == j || q2 == -1)
					{
						count2++;
						z2 = arr[i][j];
						q2 = j;
					}
				}
				if (count2 == col - 1)
				{
					return arr[i][j];
				}
			}
			else
			{
				break;
			}
		}
	}
	//第三种,判断下标一样的对角线,是否一样
	for (i = 0; i < row-1; i++)
	{
		if (arr[i][i] == arr[i + 1][i + 1] && arr[i][i] != ' ')
		{
			if (arr[i][i] == z3||z3 == 0)
			{
				count3++;
				z3 = arr[i][i];
			}
			if (count3 == row - 1)
			{
				return arr[i][i];
			}
		}
		else
		{
			break;
		}
	}
	//第四种,判断下标不一样的对角线,是否一样
	for (i = 0; i < row - 1; i++)
	{
		if (arr[i][row-1-i] == arr[i+1][row-i-2] && arr[i][row-1-i] != ' ')
		{
			if (arr[i][row-1-i] == z4 || z4 == 0)
			{
				count4++;
				z4 = arr[i][row-1-i];
			}
			if (count4 == row - 1)
			{
				return arr[i][row-1-i];
			}
		}
		else
		{
			break;
		}
	}
	Isfull(arr, ROW, COL);
}
char Isfull(char arr[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < COL; j++)
		{
			if (arr[i][j] == ' ')
			{
				return 'C';
			}
		}
	}
	return 'Q';
}
//int Isqual(char z)
//{
//	int count = 0;
//	char q = 0;
//	q = z;
//	if (q == z)
//	{
//		count++;
//	}
//}

Two: Some examples in the code illustrate

Most of them are in the comments, here is only a small part

1. For example, when judging whether the chess pieces are the same when judging the row, why are there two constraints of a z and a q

Because if the following situations occur, it will also be judged as a win.

If z is not set and q is not set, the following situations will occur (this will cause one party to win)

 If there are no these two constraints, the code is as follows (fragment)

for (i = 0; i < row; i++)
	{
		for (j = 0; j < col-1; j++)
		{
			if (arr[i][j] == arr[i][j + 1]&& arr[i][j]!=' ')
			{
						count1++;
				if (count1 == row - 1)
				{
					return arr[i][j];
				}
			}
			else
			{
				break;
			}
		}
	}

If only z is set, it can ensure that the chess pieces before and after are the same, but it cannot prevent the following situation

 So it is necessary to set a q guarantee that the number of rows is the same.

2. The logic of rows and columns is the same, and the diagonal line does not need to set q, because there is only one direction for comparison, only the situation similar to the following

3. It is this part that realizes not only the operation of backgammon. You can try it, try backgammon, and backgammon hahaha. If you don’t understand, you can leave a message, and if you can’t solve it, you can ask me~

The following is the 10 backgammon I tried, and I feel a sense of accomplishment! !

keep it up!

Maybe the description is not perfect enough, if you don’t understand, you can ask me! 

One more thing to add, let’s write the random number in the next article~

Please correct me if I am wrong! thank you readers

Guess you like

Origin blog.csdn.net/m0_57549888/article/details/124086559