三子棋小游戏(C语言)

C语言三子棋小游戏

提示:本文使用的编码环境为VS2013


前言

三子棋为3 X 3的九格棋盘,由人机对弈,其中任一方先三子联成一条直线为则视为胜出,如九格下满双方都未有三子成线则为平局。对弈过程由玩家输入坐标操作完成,根据输入坐标的位置来确定棋子的位置。

一、实现方式

1.主函数

代码如下:

#include "game.h"
// main.c
int main()
{
	
	while (1)
	{
		int choice = 0;
		int i = Meun(choice);
		switch (i)
		{
		case 1:
			Game();
			break;
		case 2:
			printf("再见!\n");
			break;
		default:
			printf("输入有误!\n");
			break;
		}
	}
	

	system("pause");
	return 0;
}

2.主要函数分析

2.1 棋盘界面

代码如下:

static void ChessBoard(char board[][COL], int row, int col)
{   /*棋盘界面*/
	printf("     1   2   3  \n");
	printf("   +---+---+---+\n");
	for (int row = 0; row < ROW; row++)
	{
		printf("%d", row + 1);
		printf("  | %c | %c | %c |\n", board[row][0],
			board[row][1], board[row][2]);//memset(board,' ',sizeof(board)); %c 打印空格。
		printf("   +---+---+---+\n");
	}
}

注意事项
静态函数使用

static void ChessBoard(char board[][COL], int row, int col)

函数也有存储类别, 可以是外部函数(默认)静态函数。 外部函数可以被其他文件的函数访问, 但是静态函数只能用于其定义所在的文件。 假设一个文件中包含了以下函数原型:
double gamma(double); /* 该函数默认为外部函数 */
static double beta(int, int);
extern double delta(double, int);
在同一个程序中, 其他文件中的函数可以调用gamma()和delta(), 但是不能调用beta(), 因为以static存储类别说明符创建的函数属于特定模块私有。 这样做避免了名称冲突的问题, 由于beta()受限于它所在的文件, 所以在其他文件中可以使用与之同名的函数。
通常的做法是: 用extern 关键字声明定义在其他文件中的函数。 这样做是为了表明当前文件中使用的函数被定义在别处。 除非使用static关键字,否则一般函数声明都默认为extern
二维数组的函数调用
char board[][COL] 形参实例化时,二维数组降维成数组指针,所以初始化二维数组的第二个[COL]必须有值。第1个形参告诉函数该数组的地址和数据类型, 第2个形参告诉函数该数组中元素的个数

2.2 电脑落子

static void ComputerMove(char board[][COL], int row, int col)
{  /*电脑落子*/
	while (1)
	{
		int x = rand() % row;//如要产生[m,n]范围内的随机数num,可用:int num = rand() % (n - m + 1) + m;
		int y = rand() % col;//产生一个[0,clo-1]数
		if (board[x][y] == ' ')
		{
			board[x][y] = C_COLOR;
			break;
		}
	}
}

注意事项

int x = rand() % row;

rand()是“伪随机数生成器”, 意思是可预测生成数字的实际序列。 但是, 数字在其取值范围内均匀分布。
int num = rand() % (n - m + 1) + m; 产生[m,n]范围内的随机数num。int x = rand() % row;则产生[0,2]的随机数。

2.3 游戏判断

void Game()
{
	srand((unsigned long)time(NULL));//种一个随机数种子
	char board[ROW][COL];
	memset(board,' ',sizeof(board));//将数组board用空格替换;sizeof(board)代表整个数组大小
	char result = 'x';
	do{
		ChessBoard(board, ROW, COL);
		PlayerMove(board, ROW, COL);
		result = Judge(board, ROW, COL);
		if (result != NEXT)
		{
			break;
		}
		ComputerMove(board, ROW, COL);
		result = Judge(board, ROW, COL);
		if (result != NEXT)
		{
			break;
		}
	} while (1);
		if (P_COLOR == result)
		{
			printf("你赢了!\n");
		}
		else if (C_COLOR == result)
		{
			printf("你输了!\n");
		}
		else
		{
			printf("和棋!\n");
		}
		ChessBoard(board, ROW, COL);
}

注意事项

srand((unsigned long)time(NULL));

种一个随机数种子。

memset(board,' ',sizeof(board));

memset() 函数可以说是初始化内存的“万能函数”,通常为新申请的内存进行初始化工作。它是直接操作内存空间,mem即“内存”(memory)的意思。

void *memset(void *s, int c, unsigned long n);

该函数的功能是:将指针变量 s 所指向的前 n 字节的内存单元用一个“整数” c 替换,注意 c 是 int 型。s 是 void* 型的指针变量,所以它可以为任何类型的数据进行初始化。

二、全部代码

1.game.c文件

#include "game.h"

int Meun(int choice)
{
	printf("*************************************\n");
	printf("****   1.Play    ***    2.Exit   ****\n");
	printf("*************************************\n");
	printf("请选择:");
	scanf("%d", &choice);
	return choice;
}

//char board[][COL] 形参实例化时,二维数组降维成数组指针,
//所以初始化二维数组的第二个[COL]必须有值。
//静态函数只能本game.c文件中调用。
static void ChessBoard(char board[][COL], int row, int col)
{   /*棋盘界面*/
	printf("     1   2   3  \n");
	printf("   +---+---+---+\n");
	for (int row = 0; row < ROW; row++)
	{
		printf("%d", row + 1);
		printf("  | %c | %c | %c |\n", board[row][0],
			board[row][1], board[row][2]);//memset(board,' ',sizeof(board)); %c 打印空格。
		printf("   +---+---+---+\n");
	}
}

static void PlayerMove(char board[][COL], int row, int col)
{   /*棋手落子*/
	int x = 0;
	int y = 0;
	int quit = 0;
	while (1){
		printf("请输入你的位置# ");
		scanf("%d %d", &x, &y);
		if (x < 1 || x > 3 || y < 1 || y > 3)
		{
			printf("你输入的坐标有误!\n");
			continue;
		}
		else if (board[x - 1][y - 1] != ' ')
		{
			printf("该位置已经被占用!\n");
			continue;
		}
		else
		{
			board[x - 1][y -1] = P_COLOR;
			break;
		}
	}
}

static char Judge(char board[][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[1][1] == board[2][2] && \
		board[0][0] != ' ')//"\"三子连珠
	{
		return board[1][1];
	}

	if (board[0][2] == board[1][1] && \
		board[1][1] == board[2][0] && \
		board[1][1] != ' ')//"/"三子连珠
	{
		return board[1][1];
	}

	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
			{
				return NEXT;//还有空位,正在落子。
			}
		}
	}

	return DRAW;//没有空位,和棋平局。
}

static void ComputerMove(char board[][COL], int row, int col)
{  /*电脑落子*/
	while (1)
	{
		int x = rand() % row;//如要产生[m,n]范围内的随机数num,可用:int num = rand() % (n - m + 1) + m;
		int y = rand() % col;//产生一个[0,clo-1]数
		if (board[x][y] == ' ')
		{
			board[x][y] = C_COLOR;
			break;
		}
	}
}

void Game()
{
	srand((unsigned long)time(NULL));//种一个随机数种子
	char board[ROW][COL];
	memset(board,' ',sizeof(board));//将数组board用空格替换;sizeof(board)代表整个数组大小
	char result = 'x';
	do{
		ChessBoard(board, ROW, COL);
		PlayerMove(board, ROW, COL);
		result = Judge(board, ROW, COL);
		if (result != NEXT)
		{
			break;
		}
		ComputerMove(board, ROW, COL);
		result = Judge(board, ROW, COL);
		if (result != NEXT)
		{
			break;
		}
	} while (1);
		if (P_COLOR == result)
		{
			printf("你赢了!\n");
		}
		else if (C_COLOR == result)
		{
			printf("你输了!\n");
		}
		else
		{
			printf("和棋!\n");
		}
		ChessBoard(board, ROW, COL);
}

2.game.c文件

#ifndef __GAME_H__
#define __GAME_H__

#include <stdio.h>
#include <windows.h>
#include <time.h>
#pragma warning(disable:4996)

#define ROW 3
#define COL 3

#define P_COLOR 'X'
#define C_COLOR 'O'
#define NEXT 'N'
#define DRAW 'D'

int Meun(int choice);
void Game();



#endif

三、运行结果

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值