【C语言】三子棋详解(电脑智能下棋算法)

这期内容:
1.这期重点对棋盘美化
2.智能选择玩家和电脑谁先走(7中test.c)
3.和电脑智能化下棋做了代码实现!!(跳转4,和test.c中有对这个进行实现!!)

上期内容:

  1. 打印菜单
  2. 创建数组存放数据,利用循环创造一个三子棋的基本外框,创建数组存放数据–打印的结果跟这个注释的差不多,个人觉得三子棋循环的时候可以暴力一些
  3. 初始化数组内容
  4. 玩家 电脑下棋( 判断平局,玩家赢,电脑赢等情况)–此处的玩家下棋可以考虑玩家以为坐标从(1,1)开始,我们在这里假设以玩家先下棋---------这些为上期主要内容如不清楚请跳转下面链接!!!
  5. c语言实现三子棋初级

效果图

在这里插入图片描述

从这里我们可以看到,电脑会自动拦截我们的子,并且在二子的时候判断是截断还是下棋取胜!取胜的优先级是在拦截前面的!!
本期主要带大家来写智能电脑端下棋!!

一、如何制作三子棋?

在这里插入图片描述

1.打印菜单

代码如下(示例):

void meau()
{
	printf("************************************\n");
	printf("*********1.开始游戏 ****************\n");
	printf("*********2.退出游戏*****************\n");
	printf("************************************\n");
}

2.创建数组,构建框架

代码如下(示例):

void InitBoard(char a[ROW][COL], int row, int col)
{
	//我们往创建的a数组里面放入空格
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			a[i][j] = ' ';
		}
	}
}

3.游戏实现

void game()
{
	char a[ROW][COL];
	CreatBoard(a);
	char ret = 0;
	int q =  rand() % 2;//电脑玩家随机下棋
	if (q == 1)
	{
		while (1)
		{
		PlayerMove(a, ROW, COL);
		ret=isWin(a, ROW, COL);
		if (ret != 'Q')
			break;
		ComputerMove(a, ROW, COL);
		ret = isWin(a, ROW, COL);
		if (ret != 'Q')
			break;
		}
	}
	else
	{
		while (1)
		{
			ComputerMove(a, ROW, COL);
			ret = isWin(a, ROW, COL);
			if (ret != 'Q')
				break;
			PlayerMove(a, ROW, COL);
			ret = isWin(a, ROW, COL);
			if (ret != 'Q')
				break;
		}
	}
	if (ret == '*')
	{
		printf("玩家赢\n");
	}
	if (ret == '#')
	{
		printf("电脑赢\n");
	}
	if (ret == 'C')
	{
		printf("平局\n");
	}
}
4.智能判断判断输赢
int JudgePlayerMove(char a[ROW][COL], int row, int col)
{
	int q = 0;
	//这里我们先判断玩家是否是要赢了
	for (int i = 0; i <= 2; i++)
	{
		if (a[i][0] == a[i][1] && a[i][0] == '*' && a[i][2] == ' ')
		{
			a[i][2] = '#';
			q = 1;//q在这里表示我们已经下过棋了!!
			return q;
		}
			if (a[i][0] == a[i][2] && a[i][2] == '*' && a[i][1] == ' ')
			{
				a[i][1] = '#';
				q = 1;
				return q;
			}
			if (a[i][1] == a[i][2] && a[i][1] == '*' && a[i][0] == ' ')
			{
				a[i][0] = '#';
				q = 1;
				return q;
			}
	}
	
	//走到这里行的三种情况都考虑了
//接下来走列
	for (int i = 0; i <= 2; i++)
	{
		if (a[0][i] == a[1][i] && a[1][i] == '*' && a[2][i] == ' ')
		{
			a[2][i] = '#';
			q = 1;
			return q;
		}
		if (a[0][i] == a[2][i] && a[2][i] == '*' && a[1][i] == ' ')
		{
			a[1][i] = '#';
			q = 1;
			return q;
		}
		if (a[2][i] == a[1][i] &&a[1][i]== '*' && a[0][i] == ' ')
		{
			a[0][i] = '#';
			q = 1;
			return q;
		}
	}
		//走到这里还差捺
	if (a[0][0] == a[1][1] && a[1][1] == '*' && a[2][2] == ' ')
	{
		a[2][2] = '#';
		q = 1;
		return q;
	}
	if (a[0][0] == a[2][2] && a[0][0] == '*' && a[1][1] == ' ')
	{
		a[1][1] = '#';
		q = 1;
		return q;
	}
	if (a[1][1] == a[2][2] && a[1][1] == '*' && a[0][0] == ' ')
	{
		a[0][0] = '#';
		q = 1;
		return q;
	}
	//撇
	if (a[0][2] == a[1][1] && a[1][1] == '*' && a[2][0] == ' ')
	{
		a[2][0] = '#';
		q = 1;
		return q;
	}
	if (a[0][2] == a[2][0] && a[0][2] == '*' && a[1][1] == ' ')
	{
		a[1][1] = '#';
		q = 1;
		return q;
	}
	if (a[1][1] == a[2][0] && a[1][1] == '*' && a[0][2] == ' ')
	{
		a[0][2] = '#';
		q = 1;
		return q;
	}
	return q;
}
//电脑#  玩家*
int Computer_IMove(char a[ROW][COL], int row, int col)
{

	//先考虑电脑已经连续下了两个棋并且在对应的行或者列
	int q = 0;
	for (int i = 0; i <= 2; i++)
	{
		if (a[i][0] == a[i][1] && a[i][0]  == '#' && a[i][2] == ' ')
		{
			a[i][2] = '#';
			q = 1;//q在这里表示我们已经下过棋了!!
			return q;
		}
		if (a[i][0] == a[i][2] && a[i][0] == '#' && a[i][1] == ' ')
		{
			a[i][1] = '#';
			q = 1;
			return q;
		}
		if (a[i][0] == a[i][2] && a[i][0] == '#' && a[i][1] == ' ')
		{
			a[i][0] = '#';
			q = 1;
			return q;
		}
	}
	//接下来走列
	for (int i = 1; i <= 2; i++)
	{
		if (a[0][i] == a[1][i] && a[0][i] == '#' && a[2][i] == ' ')
		{
			a[2][i] = '#';
			q = 1;
			return q;
		}
		if (a[0][i] == a[2][i] && a[0][i] == '#' && a[1][i] == ' ')
		{
			a[1][i] = '#';
			q = 1;
			return q;
		}
		if (a[2][i] == a[1][i] && a[1][i] == '#' && a[0][i] == ' ')
		{
			a[0][i] = '#';
			q = 1;
			return q;
		}
	}
	//走到这里还差捺
	if (a[0][0] == a[1][1] && a[0][0] == '#' && a[2][2] == ' ')
	{
		a[2][2] = '#';
		q = 1;
		return q;
	}
	if (a[0][0] == a[2][2] && a[0][0] == '#' && a[1][1] == ' ')
	{
		a[1][1] = '#';
		q = 1;
		return q;
	}
	if (a[1][1] == a[2][2] && a[1][1] == '#' && a[0][0] == ' ')
	{
		a[0][0] = '#';
		return q;
	}
	//撇
	if (a[0][2] == a[1][1] && a[0][2] == '#' && a[2][0] == ' ')
	{
		a[2][0] = '#';
		q = 1;
		return q;
	}
	if (a[0][2] == a[2][0] && a[2][0] == '#' && a[1][1] == ' ')
	{
		a[1][1] = '#';
		q = 1;
		return q;
	}
	if (a[1][1] == a[2][0] && a[2][0] == '#' && a[0][2] == ' ')
	{
		a[0][2] = '#';
		q = 1;
		return q;
	}
	//走到这里,只要有两个连续放着的,都会被电脑赢



	//如果那些状态都不满足,就返回q
	return q;//q==0的时候随机生成坐标下棋
}
5. 玩家,电脑下棋与判断输赢
void PlayerMove(char a[ROW][COL], int row, int col)
{
	printf("--------------玩家下棋--------------\n");
	//先判断这个位置是否为空,如果为空则重新选择
	int x = 0; int y = 0;
	int i = 0;
	while (1)
	{
		if(i==0)
	printf("请输入坐标 x,y: ");
	scanf("%d %d", &x, &y);
	if (x >=1 && x <= row && y >=1 && y <= col)
	{
		if (a[x - 1][y - 1] == ' ')
		{
			a[x - 1][y - 1] = '*';
			DisplayBoard(a, col, row);
			break;
		}
	}
	else
	{
		printf("输入坐标错误,请重新输入\n");
		i = 1;
	}
	}		
	//在这里下棋后我们打印出来出来看看
}
void ComputerMove(char a[ROW][COL], int row, int col)
{
	printf("电脑下棋\n");
	while (1)
	{
	int x = rand() % row;
	int y = rand() % col;
	if (a[x][y] == ' ')
	{
		a[x ][y ] = '#';
		DisplayBoard(a, col, row);
		break;
	}
	}
}
char isFull(char a[ROW][COL], int row, int col)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (a[i][j] == ' ')
				return 'Q';
		}
	}
	return 'C';
}

//iswin
//返回 * 玩家赢 ,#电脑赢,Q继续,C平局
char isWin(char a[ROW][COL], int row, int col)
{
	//交叉
	if (a[0][0] == a[1][1] && a[2][2] == a[1][1]  && a[0][0] != ' ')
	return a[0][0];
	if (a[0][2] == a[1][1] && a[1][1] == a[2][0]  && a[0][2] != ' ')
		return a[0][2];
	//三横
	if (a[0][0] == a[0][1] && a[0][1] == a[0][2] && a[0][1] != ' ')
		return a[0][1];
	if (a[1][1] == a[1][2] && a[1][2] == a[1][3] && a[1][1] != ' ')
		return a[1][1];
	if (a[2][1] == a[2][2] && a[2][2] == a[2][3] && a[2][1] != ' ')
		return a[2][1];
	//三竖
	if (a[0][0] == a[1][0] && a[1][0] == a[2][0] && a[0][0] != ' ')
		return a[0][0];
	if (a[0][1] == a[1][1] && a[1][1] == a[2][1] && a[1][1] != ' ')
		return a[0][1];
	if (a[0][2] == a[1][2] && a[1][2] == a[2][2] && a[2][2] != ' ')
		return a[0][2];

	return isFull(a, row, col);
}
6.附上全部代码
———————————————————————————game.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
void InitBoard(char a[ROW][COL], int row, int col);
void PlayerMove(char a[ROW][COL], int row, int col);
void DisplayBoard(char a[ROW][COL], int row, int col);
void ComputerMove(char a[ROW][COL], int row, int col);
char isWin(char a[ROW][COL], int row, int col);
int JudgePlayerMove(char a[ROW][COL], int row, int col);
int Computer_IMove(char a[ROW][COL], int row, int col);
__________________________________game.c
#define  _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char a[ROW][COL], int row, int col)
{
	//我们往创建的a数组里面放入空格
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			a[i][j] = ' ';
		}
	}
}
void DisplayBoard(char a[ROW][COL], int row, int col)
{
	//我们再把三子棋的外框架弄出来
	int k = 0;
	int j = 0;
	int i = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf("+---");
		}
		printf("+\n");
		printf("+");
		for (k = 0; k < col; k++)
		{
			if (k < col - 1)
				printf(" %c |", a[i][k]);
		}
		printf(" %c +\n", a[i][col - 1]);//这个地方要注意我们要退出这里的时候要把这里置成空
	}
	for (int j = 0; j < col; j++)
	{
		printf("+---");
	}
	printf("+\n");
}
void PlayerMove(char a[ROW][COL], int row, int col)
{
	printf("--------------玩家下棋--------------\n");
	//先判断这个位置是否为空,如果为空则重新选择
	int x = 0; int y = 0;
	int i = 0;
	while (1)
	{
		if(i==0)
	printf("请输入坐标 x,y: ");
	scanf("%d %d", &x, &y);
	if (x >=1 && x <= row && y >=1 && y <= col)
	{
		if (a[x - 1][y - 1] == ' ')
		{
			a[x - 1][y - 1] = '*';
			DisplayBoard(a, col, row);
			break;
		}
	}
	else
	{
		printf("输入坐标错误,请重新输入\n");
		i = 1;
	}
	}		
	//在这里下棋后我们打印出来出来看看
}
void ComputerMove(char a[ROW][COL], int row, int col)
{
	printf("电脑下棋\n");
	while (1)
	{
	int x = rand() % row;
	int y = rand() % col;
	if (a[x][y] == ' ')
	{
		a[x ][y ] = '#';
		DisplayBoard(a, col, row);
		break;
	}
	}
}
char isFull(char a[ROW][COL], int row, int col)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (a[i][j] == ' ')
				return 'Q';
		}
	}
	return 'C';
}

//iswin
//返回 * 玩家赢 ,#电脑赢,Q继续,C平局
char isWin(char a[ROW][COL], int row, int col)
{
	//交叉
	if (a[0][0] == a[1][1] && a[2][2] == a[1][1]  && a[0][0] != ' ')
	return a[0][0];
	if (a[0][2] == a[1][1] && a[1][1] == a[2][0]  && a[0][2] != ' ')
		return a[0][2];
	//三横
	if (a[0][0] == a[0][1] && a[0][1] == a[0][2] && a[0][1] != ' ')
		return a[0][1];
	if (a[1][1] == a[1][2] && a[1][2] == a[1][3] && a[1][1] != ' ')
		return a[1][1];
	if (a[2][1] == a[2][2] && a[2][2] == a[2][3] && a[2][1] != ' ')
		return a[2][1];
	//三竖
	if (a[0][0] == a[1][0] && a[1][0] == a[2][0] && a[0][0] != ' ')
		return a[0][0];
	if (a[0][1] == a[1][1] && a[1][1] == a[2][1] && a[1][1] != ' ')
		return a[0][1];
	if (a[0][2] == a[1][2] && a[1][2] == a[2][2] && a[2][2] != ' ')
		return a[0][2];

	return isFull(a, row, col);
}
int JudgePlayerMove(char a[ROW][COL], int row, int col)
{
	int q = 0;
	//这里我们先判断玩家是否是要赢了
	for (int i = 0; i <= 2; i++)
	{
		if (a[i][0] == a[i][1] && a[i][0] == '*' && a[i][2] == ' ')
		{
			a[i][2] = '#';
			q = 1;//q在这里表示我们已经下过棋了!!
			return q;
		}
			if (a[i][0] == a[i][2] && a[i][2] == '*' && a[i][1] == ' ')
			{
				a[i][1] = '#';
				q = 1;
				return q;
			}
			if (a[i][1] == a[i][2] && a[i][1] == '*' && a[i][0] == ' ')
			{
				a[i][0] = '#';
				q = 1;
				return q;
			}
	}
	
	//走到这里行的三种情况都考虑了
//接下来走列
	for (int i = 0; i <= 2; i++)
	{
		if (a[0][i] == a[1][i] && a[1][i] == '*' && a[2][i] == ' ')
		{
			a[2][i] = '#';
			q = 1;
			return q;
		}
		if (a[0][i] == a[2][i] && a[2][i] == '*' && a[1][i] == ' ')
		{
			a[1][i] = '#';
			q = 1;
			return q;
		}
		if (a[2][i] == a[1][i] &&a[1][i]== '*' && a[0][i] == ' ')
		{
			a[0][i] = '#';
			q = 1;
			return q;
		}
	}
		//走到这里还差捺
	if (a[0][0] == a[1][1] && a[1][1] == '*' && a[2][2] == ' ')
	{
		a[2][2] = '#';
		q = 1;
		return q;
	}
	if (a[0][0] == a[2][2] && a[0][0] == '*' && a[1][1] == ' ')
	{
		a[1][1] = '#';
		q = 1;
		return q;
	}
	if (a[1][1] == a[2][2] && a[1][1] == '*' && a[0][0] == ' ')
	{
		a[0][0] = '#';
		q = 1;
		return q;
	}
	//撇
	if (a[0][2] == a[1][1] && a[1][1] == '*' && a[2][0] == ' ')
	{
		a[2][0] = '#';
		q = 1;
		return q;
	}
	if (a[0][2] == a[2][0] && a[0][2] == '*' && a[1][1] == ' ')
	{
		a[1][1] = '#';
		q = 1;
		return q;
	}
	if (a[1][1] == a[2][0] && a[1][1] == '*' && a[0][2] == ' ')
	{
		a[0][2] = '#';
		q = 1;
		return q;
	}
	return q;
}
//电脑#  玩家*
int Computer_IMove(char a[ROW][COL], int row, int col)
{

	//先考虑电脑已经连续下了两个棋并且在对应的行或者列
	int q = 0;
	for (int i = 0; i <= 2; i++)
	{
		if (a[i][0] == a[i][1] && a[i][0]  == '#' && a[i][2] == ' ')
		{
			a[i][2] = '#';
			q = 1;//q在这里表示我们已经下过棋了!!
			return q;
		}
		if (a[i][0] == a[i][2] && a[i][0] == '#' && a[i][1] == ' ')
		{
			a[i][1] = '#';
			q = 1;
			return q;
		}
		if (a[i][0] == a[i][2] && a[i][0] == '#' && a[i][1] == ' ')
		{
			a[i][0] = '#';
			q = 1;
			return q;
		}
	}
	//接下来走列
	for (int i = 1; i <= 2; i++)
	{
		if (a[0][i] == a[1][i] && a[0][i] == '#' && a[2][i] == ' ')
		{
			a[2][i] = '#';
			q = 1;
			return q;
		}
		if (a[0][i] == a[2][i] && a[0][i] == '#' && a[1][i] == ' ')
		{
			a[1][i] = '#';
			q = 1;
			return q;
		}
		if (a[2][i] == a[1][i] && a[1][i] == '#' && a[0][i] == ' ')
		{
			a[0][i] = '#';
			q = 1;
			return q;
		}
	}
	//走到这里还差捺
	if (a[0][0] == a[1][1] && a[0][0] == '#' && a[2][2] == ' ')
	{
		a[2][2] = '#';
		q = 1;
		return q;
	}
	if (a[0][0] == a[2][2] && a[0][0] == '#' && a[1][1] == ' ')
	{
		a[1][1] = '#';
		q = 1;
		return q;
	}
	if (a[1][1] == a[2][2] && a[1][1] == '#' && a[0][0] == ' ')
	{
		a[0][0] = '#';
		return q;
	}
	//撇
	if (a[0][2] == a[1][1] && a[0][2] == '#' && a[2][0] == ' ')
	{
		a[2][0] = '#';
		q = 1;
		return q;
	}
	if (a[0][2] == a[2][0] && a[2][0] == '#' && a[1][1] == ' ')
	{
		a[1][1] = '#';
		q = 1;
		return q;
	}
	if (a[1][1] == a[2][0] && a[2][0] == '#' && a[0][2] == ' ')
	{
		a[0][2] = '#';
		q = 1;
		return q;
	}
	//走到这里,只要有两个连续放着的,都会被电脑赢



	//如果那些状态都不满足,就返回q
	return q;//q==0的时候随机生成坐标下棋
}
_________________________test.c
#define  _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//玩家下棋用*,电脑下棋用#
//1.打印菜单
//2.创建字符数组并且初始化
//3.把那个三子棋的框架弄出来
//4.智能判断电脑是否快要取胜 !!(这部的优先级是要大于第五步的)
//5.智能拦截玩家的棋
//6.玩家走,电脑走
//7.判断输赢
void CreatBoard(char a[ROW][COL])
{
	InitBoard(a, ROW, COL);
}
void game()
{
	char a[ROW][COL];
	CreatBoard(a);
	char ret = 0;
	int q =rand() % 2;
	if (q == 1)
	{
		DisplayBoard(a, ROW, COL);
		while (1)
		{
		PlayerMove(a, ROW, COL);
		ret=isWin(a, ROW, COL);
		if (ret != 'Q')
			break;	
		int i= Computer_IMove(a, ROW, COL);
		if (i == 0)
		{
			int z = JudgePlayerMove(a, ROW, COL);
			if (z == 0)
			{
			ComputerMove(a, ROW, COL);
			}
			else
			{
				DisplayBoard(a, ROW, COL);
			}
		}	
		else
		{
			DisplayBoard(a, ROW, COL);
		}
		ret = isWin(a, ROW, COL);
		if (ret != 'Q')
			break;
		}
	}
	else
	{
		int b = 0;
		while (1)
		{	
			if (b == 0)
			{
				printf("--------------电脑下棋--------------\n");
				a[1][1] = '#';//这里是因为一开始下中间的话相当于排除了玩家下棋赢棋的三种可能性,所以第一步我们固定电脑下在中间(假设下在第一行第一列,只能保证玩家在第一行第一列没办法取胜!)
				b = 1;
			    DisplayBoard(a, ROW, COL);
			}	
			else
			{
				if (b == 2)
				{
			int i = Computer_IMove(a, ROW, COL);
			if (i == 0)
			{
				int z = JudgePlayerMove(a, ROW, COL);
				if (z == 0)
				{
					ComputerMove(a, ROW, COL);
				}
				else
				{
					printf("--------------电脑下棋--------------\n");
					DisplayBoard(a, ROW, COL);
				}
			}
			else
			{
				printf("--------------电脑下棋--------------\n");
				DisplayBoard(a, ROW, COL);
			}
			ret = isWin(a, ROW, COL);
			if (ret != 'Q')
				break;
			}
			PlayerMove(a, ROW, COL);
			ret = isWin(a, ROW, COL);
			if (ret != 'Q')
				break;
			b = 2;	
			}	
		}
	}
	if (ret == '*')
	{
		printf("玩家赢\n");
	}
	if (ret == '#')
	{
		printf("电脑赢\n");
	}
	if (ret == 'C')
	{
		printf("平局\n");
	}
}
void meau()
{
	printf("************************************\n");
	printf("*********1.开始游戏 ****************\n");
	printf("*********2.退出游戏*****************\n");
	printf("************************************\n");
}
int main()
{
	srand((unsigned)time(NULL));
	int input = 0;
	do
	{
		meau();
		printf("请输入数字1或0\n");
		int ret = scanf("%d", &input);
		if (input == 0)
		{
			printf("退出游戏");
			break;
		}
		else if (input == 1)
		{
			game();
		}
		else
		{
			printf("请重新输入\n");
		}
	} while (input);
	return 0;
}
7.附上代码链接

码云:https://gitee.com/wuyi-ljh/test-43—testing/commit/846a6550530ed01a2eb8f2b3ccd1feeaa41f9239

总结

提示:这篇文章虽然之前写过一次,加多了个电脑智能化和玩家下棋,要弄清楚逻辑,比较适合新手,文章内有什么问题都可以私信我,觉得写的还不错的可以给个一键三连支持哦,这对我很重要!!

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

^jhao^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值