三子棋(C语言)

目录

三子棋(未优化)

game.h

game.c

text.c

三子棋(优化)

●优化computerMove函数

●computerMove函数


三子棋(未优化)

game.h

#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 3
#define COL 3
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void menu();
void intiboard(char board[ROW][COL], int row, int col);
void playmove(char board[ROW][COL], int row, int col);
void display(char board[ROW][COL], int row, int col);
void computermove(char  board[ROW][COL], int row,int col);
char if_win(char board[ROW][COL], int row,int col);
int if_full(char board[ROW][COL], int row, int col);

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
	printf("********************\n");
	printf("******1---play******\n");
	printf("******0---exit******\n");
	printf("********************\n");
}
void intiboard(char board[ROW][COL], int row, int col)//棋盘初始化
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}
void display(char board[ROW][COL], int row, int col)//打印棋盘
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		if (i < row - 1)
		{
			for (int j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}
	}
}
void playmove(char board[ROW][COL], int row, int col)//玩家下棋
{
	int x = 0, y = 0;//这里注意玩家输入的x,y是从1开始
	while (1)
	{
		scanf("%d %d", &x, &y);
		if (x >=1  && y >= 1)
		{
			if (board[x - 1][y - 1] == ' ')//把玩家的(x,y)转换为数组下标
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
				printf("该格已占,请重新输入\n");
		}
	}
}
//a a a
//a a a
//a a a
void computermove(char board[ROW][COL], int row, int col)//电脑下棋
{
	int x = 0, y = 0;
	while (1)
	{
		x = rand() % 3;
		y = rand() % 3;
		if (board[x ][y ] == ' ')//注意数组越界
		{

			board[x ][y ] = '#';
			break;
		}
	}
}
int if_full(char board[ROW][COL], int row, int col)//检查棋盘是否已满,用来判断平局
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}
char if_win(char board[ROW][COL], int row, int col)//判断输赢(行,列,对角线)
{
	for (int 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 (int j = 0; j < col; j++)
	{
		if (board[0][j] == board[1][j]&&board[1][j] == board[2][j]&&board[0][j]!=' ')
			return board[0][j];
	}
	if (board[0][0] == board[1][1] == board[2][2]&&board[0][0]!=' ')
		return board[0][0];
	if (board[0][2] == board[1][1] == board[2][0]&&board[2][0]!=' ')
		return board[0][2];
	if (if_full(board,row,col))
		return 'q';
	else
		return 'g';
}

text.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void game()
{
	char board[ROW][COL] = { 0 };
	int row = ROW;
	int col = COL;
	intiboard(board, row, col);
	display(board, row, col);
	char ret;
	while (1)
	{
		playmove(board, row, col);
		display(board, row, col);
		ret = if_win(board, row, col);//每下完一步判断一次输赢
		if (ret != 'g')
			break;
		computermove(board, row, col);
		display(board, row, col);
		ret = if_win(board, row, col);
		if (ret != 'g')
			break;
	}
	switch (ret)
	{
	case '*':
		printf("玩家胜利,游戏结束\n");
		break;
	case '#':
		printf("电脑胜利,游戏结束\n");
		break;
	case 'q':
		printf("平局,游戏结束\n");
		break;
	}
}
int main()
{
	int input = 1;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请输入1/0进入或退出游戏\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输出错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

三子棋(优化)

●优化computerMove函数

      在这里,我先说一下优化computerMove函数的思路(这里假定*为玩家,#为电脑)

(1)首先,给computerMove函数增加一个参数,count,表示玩家的下棋步数(即*在棋盘上的个数)

(2)在*在棋盘上只有一个时,电脑要在*的附近下#

(3.1)在*在棋盘上有2/3/4/5个时,电脑需要找到某一行某一列,某条对角线上,是否有两个*,和一个空格,如果符合条件,在空格处下#。

(3.2)另一种思路:在*在棋盘上只有两个时,和(3.1)执行相同的操作。在*>=3时,电脑需要先判断这步是否能使电脑胜利,若能,电脑先是自己胜利,若不符合条件,执行与3.1相同的操作

(这步没实现,如果你有执行的思路可以在自己尝试一下或者写在评论区里,感谢🤗)

(4)最后,仍然可能有电脑没考虑到的情况,所以在最后寻找空格处下棋.

●computerMove函数

(这里代码写的比较烂,就是穷举法,如果有更好的实现方法,可以在评论区中写出,感谢🤗)

void computermove(char board[ROW][COL], int row, int col,int count)
{
	int x = 0, y = 0;
	if(count==1)//玩家下一步
	for (int i = 0; i < col; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (board[i][j] == '*')
			{
				if (j == 2)
				{
					board[i][j - 1] = '#';
				}
				else
					board[i][j + 1] = '#';
			}
		}
	}
	if (count == 2||count==3||count==4||count==5)//玩家下>=2步
	{
		for (int i = 0; i < row; i++)
		{
			for (int j = 0; j < col; j++)//双层循环寻找第一个*
			{
				if (board[i][j] == '*')//在第一个*的行,列,对角线寻找第二个*,和空格并下棋
				{
					if (board[(i + 1) % 3][j] == '*')
					{
						if (board[(i + 2) % 3][j] == ' ')
						{
							board[(i + 2) % 3][j] = '#';
							return;
						}
					}
					if (board[i][(j+1)%3] == '*')
					{
						if (board[i][(j + 2) % 3] == ' ')
						{
							board[i][(j + 2) % 3] = '#';
							return;
						}
					}
					if (board[(i + 2) % 3][j] == '*')
					{
						if (board[(i + 1) % 3][j] == ' ')
						{
							board[(i + 1) % 3][j] = '#';
							return;
						}
					}
					if (board[i][(j+2)%3] == '*')
					{
						if (board[i][(j + 1) % 3] == ' ')
						{
							board[i][(j + 1) % 3] = '#';
							return;
						}
					}
					if (i == j)
					{
						if (board[(i + 1) % 3][(j + 1) % 3] == '*')
						{
							if (board[(i + 2) % 3][(j + 2) % 3] == ' ')
							{
								board[(i + 2) % 3][(j + 2) % 3] = '*';
								return;
							}
						}
						if (board[(i + 2) % 3][(j + 2) % 3] == '*')
						{
							if (board[(i + 1) % 3][(j + 1) % 3] == ' ')
							{
								board[(i + 1) % 3][(j + 1) % 3] = '*';
								return;
							}
						}
					}
					if ((i + j) == 2)
					{
						if (i == 1 && j == 1)
						{
							if (board[2][0] == '*')
							{
								if (board[0][2] == ' ')
								{
									board[0][2] = '#';
									return;
								}
							}
							if (board[0][2] == '*')
							{
								if (board[2][0] == ' ')
								{
									board[2][0] = '#';
									return;
								}
							}
						}
						if (board[j][i] == '*'&&(i!=1&&j!=1))
						{
							if (board[1][1] == ' ')
							{
								board[1][1] = '#';
								return;
							}
						}
					}
				}
			}
		}
		for (int i = 0; i < row; i++)//不符合以上情况,寻早空格下棋
		{
			for (int j = 0; j < col; j++)
			{
				if (board[i][j] == ' ')
				{
					board[i][j] = '#';
					return ;
				}
			}
		}
	}
}

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值