三子棋(C语言实现)

三子棋

    • 代码实现
      • 主函数
      • 菜单函数
      • 游戏函数
      • 初始化棋盘函数
      • 打印棋盘函数
      • 玩家放置棋子的函数
      • 电脑放置棋子的函数
      • 判断游戏的函数
      • 判断棋盘是否已满的函数
    • 完整代码
      • 头文件:game.h
      • 存放函数的文件:game.c
      • 存放主函数的文件:test.c

最近学习了C语言数组相关的基础知识, 学知识就是为了用嘛,使用知识也会让我们的学习过程更有趣。我们就用这些基础的知识写一个简单的三子棋小游戏,让我们与电脑对抗(当然,由于实力原因,这个电脑只能纯随机地放置棋子)实现效果如下图:
三子棋(C语言实现)_第1张图片
好家伙,之前我试了多少遍来故意让电脑赢,可他就是不赢,这我一写博客,想再试一次,就成功了(我只是想说我是故意输给电脑的,好面子)

代码实现

首先我们要知道,写这样一个游戏,我们会写很多行的代码,而如果这时候我们规划不得当的话,我们的代码就会变得非常乱,因此我们遵照以下规则:

  1. 把整个工程分为3个文件,test.c,game.c,game.h
  2. test.c存放main函数,用来当作程序的入口,并引用game.h头文件,即#include"game.h"
  3. game.c中存放各种各样的函数,并引用game.h头文件
  4. game.h中存放各种函数的声明以及VS提供的头文件的包含
  5. 每个函数尽量只实现一个功能,这样我们的代码会更有序,更易修改
  6. 把棋盘的行、列定义为宏,便于修改。即:
#define R 3
#define C 3
  1. 玩家放置的棋子为’*’,电脑放置的棋子为’#’, 默认的格子为’ ’
  2. 用一个3*3的二维数组来盛放整个棋盘

主函数

int main()
{
     
	int input = 0;//存放用户的选择
	srand((unsigned int)time(NULL));//设置随机数种子,后面会用到
	do//至少执行一次循环
	{
     
		menu();//打印菜单
		printf("Please enter you choice(0/1):>");//要求用户输入他的选择
		scanf("%d", &input);
		switch (input)
		{
     
		case 1:
			game();//用户输入1,进入游戏
			break;
		case 0:
			printf("Exit.\n");
			exit(886);//用户输入0,退出程序
			break;
		default:
			printf("Wrong!Please enter a right choice(0/1):>\n");//处理特殊情况
			break;
		}
	} while (input);//游戏结束后,再次进入循环
	return 0;
}

菜单函数

功能就是打印菜单

void menu()
{
     
	printf("----------------------------\n");
	printf("-----      1.play     ------\n");
	printf("-----      0.exit     ------\n");
	printf("----------------------------\n");
}

游戏函数

void game()
{
     
	char ret = 0;//用ret来判断游戏输赢,ret为'*'就代表玩家赢,为'#'就代表电脑赢,为'C'就表示继续,为'Q'就表示平局
	char arr[R][C] = {
      0 };//棋盘
	init(arr,R,C);//初始化棋盘
	show(arr,R,C);//打印棋盘
	while (1)//人机循环放置棋子
	{
     
		player(arr, R, C);
		ret=judge(arr,R,C);//放置一次,判断一次
		if (ret != 'C')//直至ret!='C',说明游戏已结束,跳出循环
		{
     
			break;
		}
		computer(arr, R, C);
		ret=judge(arr,R,C);
		if (ret != 'C')
		{
     
			break;
		}
	}
	//游戏已结束,判断结束的三种情况:人赢;电脑赢;平局。
	if (ret == '*')
	{
     
		printf("You win!\n");
	}
	else if (ret == '#')
	{
     
		printf("You lose!\n");
	}
	else
	{
     
		printf("This is a draw!\n");//draw:n.平局
	}
}

初始化棋盘函数

把棋盘都初始化为空格

void init(char arr[R][C],int r,int c)
{
     
	for (int i = 0; i < R; i++)
	{
     
		for (int j = 0; j < C; j++)
		{
     
			arr[i][j] = ' ';
		}
	}
}

打印棋盘函数

为了打印的好看,我们增加了一点别的东西

void show(char arr[R][C], int r, int c)
{
     
	int i = 0;
	for (i = 0; i < r; i++)
	{
     
		int j = 0;
		for (j = 0; j < c; j++)
		{
     
			printf(" %c ", arr[i][j]);
			if (j < c - 1)
				printf("|");
		}
		printf("\n");
		if (i < r - 1)
		{
     
			for (j = 0; j < c; j++)
			{
     
				printf("---");
				if (j < c - 1)
					printf("|");
			}
		}
		printf("\n");
	}
}

分析可知:这个函数需要在游戏开始时调用一次,而后在玩家或电脑放置棋子后调用一次

玩家放置棋子的函数

void player(char arr[R][C], int r, int c)
{
     
	printf("This is your turn,and you want to place it on:>");
	int row, col;
	scanf("%d%d", &row, &col);
	while (1)
	{
     
		if (arr[row - 1][col - 1] == ' ')//棋盘上的坐标减一才等于数组里的下标
		{
     
			arr[row - 1][col - 1] = '*';//玩家放置*
			show(arr,r,c);//放置后打印一下
			break;
		}
		else//放置的位置不是空格,说明放置的未知错误
		{
     
			printf("Wrong!Please choose again.");
		}
	}
}

电脑放置棋子的函数

void computer(char arr[R][C], int r, int c)
{
     
	printf("This is the computer's turn.");
	while (1)
	{
     
		int row = rand() % R;//随机数除以行数得到0~R-1之间的随机数
		int col = rand() % C;//同理
		if (arr[row][col] == ' ')
		{
     
			arr[row][col] = '#';//电脑放置#
			printf("And computer puts it on %d %d.\n", row + 1, col + 1);
			show(arr,r,c);
			break;
		}
	}
}

判断游戏的函数

每次玩家或电脑放置一次棋子后,我们都需要判断游戏是否已经结束

char judge(char arr[R][C],int r,int c)
{
     
	int i = 0;
	//判断一行的情况
	for (i = 0; i < r; i++)
	{
     
		if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' ')
		{
     
			return arr[i][0];//返回的值即为玩家或电脑所下的字符,分别代表玩家或电脑赢
		}
	}
	//判断一列的情况
	for (i = 0; i < c; i++)
	{
     
		if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ')
		{
     
			return arr[0][i];
		}
	}
	//判断对角线
	if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[1][1] != ' ')
		return arr[1][1];
	if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[1][1] != ' ')
		return arr[1][1];
	//判断棋盘是否已满,返回值为1时,返回'Q',代表平局
	if (full(arr, r, c))
	{
     
		return 'Q';
	}
	return 'C';//棋盘未满,返回'C',继续游戏
}

判断棋盘是否已满的函数

int full(char arr[R][C], int r, int c)//判断棋盘是否已满,未满则返回0,继续游戏,否则返回1,平局结束游戏
{
     
	int i = 0;
	int j = 0;
	for (i = 0; i < r; i++)
	{
     
		for (j = 0; j < c; j++)
		{
     
			if (arr[i][j] == ' ')
			{
     
				return 0;
			}
		}
	}
	return 1;
}

完整代码

头文件:game.h

#pragma once
#define R 3
#define C 3
#include
#include
#include
void menu();
void init(char arr[R][C],int r,int c);
void show(char arr[R][C], int r, int c);
void game();
void player(char arr[R][C], int r, int c);
void computer(char arr[R][C], int r, int c);
char judge(char arr[R][C], int r, int c);

存放函数的文件:game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void game()
{
     
	char ret = 0;//用ret来判断游戏输赢
	char arr[R][C] = {
      0 };//棋盘
	init(arr,R,C);//初始化棋盘
	show(arr,R,C);//打印棋盘
	while (1)//人机循环放置棋子
	{
     
		player(arr, R, C);
		ret=judge(arr,R,C);//放置一次,判断一次
		if (ret != 'C')//直至ret!='c',说明游戏已结束,跳出循环
		{
     
			break;
		}
		computer(arr, R, C);
		ret=judge(arr,R,C);
		if (ret != 'C')
		{
     
			break;
		}
	}
	//游戏已结束,判断结束的情况:人赢;电脑赢;平局。
	if (ret == '*')
	{
     
		printf("You win!\n");
	}
	else if (ret == '#')
	{
     
		printf("You lose!\n");
	}
	else
	{
     
		printf("This is a draw!\n");//draw:n.平局
	}
}
void player(char arr[R][C], int r, int c)
{
     
	printf("This is your turn,and you want to place it on:>");
	int row, col;
	scanf("%d%d", &row, &col);
	while (1)
	{
     
		if (arr[row - 1][col - 1] == ' ')//棋盘上的坐标减一才等于数组里的下标
		{
     
			arr[row - 1][col - 1] = '*';//玩家放置*
			show(arr,r,c);//放置后打印一下
			break;
		}
		else//放置的位置不是空格,说明放置的未知错误
		{
     
			printf("Wrong!Please choose again.");
		}
	}
}
void computer(char arr[R][C], int r, int c)
{
     
	printf("This is the computer's turn.");
	while (1)
	{
     
		int row = rand() % R;//随机数除以行数得到0~R-1之间的随机数
		int col = rand() % C;//同理
		if (arr[row][col] == ' ')
		{
     
			arr[row][col] = '#';//电脑放置#
			printf("And computer puts it on %d %d.\n", row + 1, col + 1);
			show(arr,r,c);
			break;
		}
	}
}
int full(char arr[R][C], int r, int c)//判断棋盘是否已满,未满则返回0,继续游戏,否则返回1,结束游戏
{
     
	int i = 0;
	int j = 0;
	for (i = 0; i < r; i++)
	{
     
		for (j = 0; j < c; j++)
		{
     
			if (arr[i][j] == ' ')
			{
     
				return 0;
			}
		}
	}
	return 1;
}
char judge(char arr[R][C],int r,int c)
{
     
	int i = 0;
	//判断一行的情况
	for (i = 0; i < r; i++)
	{
     
		if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' ')
		{
     
			return arr[i][0];//返回的值即为玩家或电脑所下的字符,分别代表玩家或电脑赢
		}
	}
	//判断一列的情况
	for (i = 0; i < c; i++)
	{
     
		if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ')
		{
     
			return arr[0][i];
		}
	}
	//判断对角线
	if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[1][1] != ' ')
		return arr[1][1];
	if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[1][1] != ' ')
		return arr[1][1];
	//判断棋盘是否已满,返回值为1时,返回'Q',代表平局
	if (full(arr, r, c))
	{
     
		return 'Q';
	}
	return 'C';//棋盘未满,返回'C',继续游戏
}
void menu()
{
     
	printf("----------------------------\n");
	printf("-----      1.play     ------\n");
	printf("-----      0.exit     ------\n");
	printf("----------------------------\n");
}
void init(char arr[R][C],int r,int c)
{
     
	for (int i = 0; i < R; i++)
	{
     
		for (int j = 0; j < C; j++)
		{
     
			arr[i][j] = ' ';
		}
	}
}
void show(char arr[R][C], int r, int c)
{
     
	int i = 0;
	for (i = 0; i < r; i++)
	{
     
		int j = 0;
		for (j = 0; j < c; j++)
		{
     
			printf(" %c ", arr[i][j]);
			if (j < c - 1)
				printf("|");
		}
		printf("\n");
		if (i < r - 1)
		{
     
			for (j = 0; j < c; j++)
			{
     
				printf("---");
				if (j < c - 1)
					printf("|");
			}
		}
		printf("\n");
	}
}

存放主函数的文件:test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
int main()
{
     
	int input = 0;//存放用户的选择
	srand((unsigned int)time(NULL));//设置随机数种子
	do//至少执行一次循环
	{
     
		menu();//打印菜单
		printf("Please enter you choice(0/1):>");//要求用户输入他的选择
		scanf("%d", &input);
		switch (input)
		{
     
		case 1:
			game();//用户输入1,进入游戏
			break;
		case 0:
			printf("Exit.\n");
			exit(886);//用户输入0,退出程序
			break;
		default:
			printf("Wrong!Please enter a right choice(0/1):>\n");//处理特殊情况
			break;
		}
	} while (input);
	return 0;
}

放在最后:
本人能力实在有限,不会实现图形化界面,而且这个游戏里的电脑笨的出奇,只会随机乱下,但自己会不断努力,在日后实现对此游戏的优化:如只能电脑,图形化界面等。这次就到这里吧。
另外,如果有些错误本人未察觉,欢迎大家批评指正!

你可能感兴趣的:(C语言,c语言,后端)