【C语言】三子棋的实现

一、理清逻辑

首先我们先来理一理三子棋实现的逻辑 1.打印游戏菜单 2.创建并初始化二维数组 3.打印棋盘 4.双方下棋 5.判断胜负

二、创建文件

我创建了三个文件,分别为test.c、game.h和game.c test.c文件用于实现进入游戏、退出游戏、判断输赢、打印菜单等逻辑 game.c用于编写游戏的主要实现方法 game.h存放头文件和函数的声明

三、具体步骤

1.创建菜单和实现方法

写在test.c文件中
void menu()
{
	printf("********************************
");
	printf("*********   1.play   ***********
");
	printf("*********   0.exit   ***********
");
	printf("********************************
");
}
void test()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf(":>");
		
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("三子棋游戏开始
");
			game();
			break;
		case 0:
			printf("结束游戏
");
			break;
		default:
			printf("输入错误
");
			break;

		}
	} while (input);
}

2.创建并初始化二维数组

在test.c中创建二维数组并引用初始化数组的方法
void game()
{
	//创建二维数组
	char board[ROW][COL] = { 0 };
	//初始化二维数组
	InitBoard(board, ROW, COL);
}
在game.h中用宏定义定义行列,声明函数,填写需要的头文件
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#define ROW 3
#define COL 3

在game.c中定义初始化数组的方法

#include "game.h"
void InitBoard(char board[ROW][COL],int row,int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] =  ;
		}
	}
}

3.打印棋盘

在game.c中定义打印棋盘的方法,需要注意的是每打印一行后要进行换行
void DisplayBoard(char board[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 ",board[i][j]);
			if (j < col - 1)
			{
				printf("|");
			}
		}
		printf("
");
		if (i < row - 1)
		{
			for (j = 0; j < row; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
		}
		printf("
");
	}
}
在test.c中game方法中引用此函数

4.双方下棋

人机双方轮流下棋,所以应该在test.c中将人机下棋的步骤放入循环
//下棋
	while (1)
	{
		//玩家下棋
		player_move(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//电脑下棋
		computer_move(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		ret = is_win(board, ROW, COL);
	}

1)玩家下棋

在game.c中定义实现玩家下棋的方法,要考虑到下棋是否在范围内和位置是否重复落子的情况, 因为我们是通过二维数组来实现的,所以我们输入的坐标x,y所对应的数组下标应该是x-1,y-1
void player_move(char board[ROW][COL], int row, int col)
{
	printf("玩家下棋:>");
	int x = 0;
	int y = 0;
	
	while (1)
	{
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x - 1][y - 1] ==  )
			{
				board[x - 1][y - 1] = *;
				break;
			}
			else
				printf("该坐标被占用,请重新输入!
");
		}
		else
			printf("坐标非法,请重新输入!
");
	}
	

}

2)电脑下棋

在game.c中定义电脑下棋的方法,我用的是比较简单的用rand函数生成随机数来随机建立坐标,当然这个ai算法是可以优化的。
void computer_move(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑下棋:>
");
	while (1)
	{
		x = rand() % ROW;
		y = rand() % COL;
		if (board[x][y]==  )
		{
			board[x][y] = #;
			break;
		}
	}
}

5.判断胜负

三子棋的结果无非就是三种,玩家赢,电脑赢,平局 我们先在game.c中定义一个实现判断结果的方法 任意一行相同或任意一列相同或对角线相同则视为胜利
//玩家赢:*
//电脑赢:#
//平局:Q
//继续:C
int is_full(char board[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 (board[i][j] ==  )
			{
				return 0;
			}
		}
	}
	return 1;
}
char is_win(char board[ROW][COL], int row, int 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][1] !=  )
		{
			return board[i][1];
		}
	}
	for (i = 0; i < row; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] !=  )
		{
			return board[1][i];
		}
	}
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] !=  )
	{
		return board[1][1];
	}
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] !=  )
	{
		return board[1][1];
	}
	if (is_full(board, row, col)==1)
	{
		return Q;
	}
	//继续
	return C;
}
在test.c中实现判断胜负的逻辑
char ret = 0;
	while (1)
	{
		//玩家下棋
		player_move(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != C)
		{
			break;
		}
		//电脑下棋
		computer_move(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != C)
		{
			break;
		}
	}
	//判断胜负
	if (ret == *)
	{
		printf("玩家赢了!
");
	}
	else if (ret == #)
	{
		printf("电脑赢了!
");
	}
	else
	{
		printf("平局
");
	}
}

四、运行结果

下面就来展示一下我和人工智障的精彩对局吧
嗯,看来我创造出来的ai已经强大到可以击败我了,我真厉害!

五、完整代码展示

game.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#define ROW 3
#define COL 3

void InitBoard(char board[ROW][COL], int row, int col);
void DisplayBoard(char board[ROW][COL], int row, int col);
void player_move(char board[ROW][COL], int row, int col);
void computer_move(char board[ROW][COL], int row, int col);
char is_win(char board[ROW][COL], int row, int col);
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
	printf("********************************
");
	printf("*********   1.play   ***********
");
	printf("*********   0.exit   ***********
");
	printf("********************************
");
}
void game()
{
	//创建二维数组
	char board[ROW][COL] = { 0 };
	//初始化二维数组
	InitBoard(board, ROW, COL);
	//打印棋盘
	DisplayBoard(board, ROW, COL);
	//下棋
	char ret = 0;
	while (1)
	{
		//玩家下棋
		player_move(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != C)
		{
			break;
		}
		//电脑下棋
		computer_move(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != C)
		{
			break;
		}
	}
	//判断胜负
	if (ret == *)
	{
		printf("玩家赢了!
");
	}
	else if (ret == #)
	{
		printf("电脑赢了!
");
	}
	else
	{
		printf("平局
");
	}
}
void test()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf(":>");
		
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("三子棋游戏开始
");
			game();
			break;
		case 0:
			printf("结束游戏
");
			break;
		default:
			printf("输入错误
");
			break;

		}
	} while (input);
}

int main()
{
	test();
	return 0;
}
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void InitBoard(char board[ROW][COL],int row,int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] =  ;
		}
	}
}
void DisplayBoard(char board[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 ",board[i][j]);
			if (j < col - 1)
			{
				printf("|");
			}
		}
		printf("
");
		if (i < row - 1)
		{
			for (j = 0; j < row; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
		}
		printf("
");
	}
}

void player_move(char board[ROW][COL], int row, int col)
{
	printf("玩家下棋:>");
	int x = 0;
	int y = 0;
	
	while (1)
	{
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (board[x - 1][y - 1] ==  )
			{
				board[x - 1][y - 1] = *;
				break;
			}
			else
				printf("该坐标被占用,请重新输入!
");
		}
		else
			printf("坐标非法,请重新输入!
");
	}
	

}

void computer_move(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑下棋:>
");
	while (1)
	{
		x = rand() % ROW;
		y = rand() % COL;
		if (board[x][y]==  )
		{
			board[x][y] = #;
			break;
		}
	}
}


int is_full(char board[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 (board[i][j] ==  )
			{
				return 0;
			}
		}
	}
	return 1;
}
char is_win(char board[ROW][COL], int row, int 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][1] !=  )
		{
			return board[i][1];
		}
	}
	for (i = 0; i < row; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] !=  )
		{
			return board[1][i];
		}
	}
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] !=  )
	{
		return board[1][1];
	}
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] !=  )
	{
		return board[1][1];
	}
	if (is_full(board, row, col)==1)
	{
		return Q;
	}
	//继续
	return C;
}

当然,随着所学的知识不断增加,这个游戏可以不断的被优化。

经验分享 程序员 微信小程序 职场和发展