练涛

(游戏:四子连 )四子连是一个两个人玩的棋盘游戏,在游戏中,玩家轮流将有颜色的棋子放在一个六行七列的垂直悬挂的网格中:

        这个游戏的目的是在对手实现一行、一列或者一条对角线上有四个相同颜色的棋子之前,你能先做到。程序提示两个玩家交替的下红子Red或黄子Yellow。当放下一子时,程序在控制台重新显示这个棋盘,然后确定游戏状态(赢、平局还是继续),下面是一个运行示例:

 

。。。

。。。

。。。

 

                                                                                                            -----此题源自《java语言程序设计》习题8.20

目录

对象分析:

胜出条件:四子连珠

Java(最终代码):

C++(第1版,有点乱):

 


对象分析:

        属性:棋盘:Graph、top——二维字符(串)组模拟栈组;

                   棋子:C(颜色)——奇偶交替变换

                   棋盘剩余空格:empty——用于判断平局

        方法:下棋:input()——修改二维组

                   判断输赢:judge()——判断胜出

                   显示棋盘:show()——展示棋盘

胜出条件:四子连珠

              代码思路:每次下棋之后都要进行判断,是否有人胜出,怎么判断呢?可以在下棋之后,以此棋为中心,向四个方向(水平,垂直,两条对角线:通过坐标的加减)判断是否出现了四子连珠(注意边界,易出现bug),具体实现,请看代码。

                                当然也可以在整个棋盘搜索,代码容易写,但降低了效率。

               注意:边界要判断仔细

                          双向检测连珠,有可能你最后一次是下3个棋子中间胜出

Java(最终代码):

        java作业,可参考,别抄.

        judge(递归实现):单向探测求和,(也可双向,但效率没提高多少,且可读性不高)

import java.util.Scanner;
public class JavaGame {
	int row,column;                       //行列
	char Graph[][];                       //二维棋盘
	int top[];		                      //模拟栈尾指针
	String C[]={"red","yellow"};          //棋子颜色
	int empty;                            //棋盘剩余空格
    public JavaGame(int r,int c){                  //初始化棋盘数据
    	empty=r*c;
    	row=r;column=c;
    	Graph=new char[r][c];
    	top=new int[c];
    	for(int i=0;i<c;i++)                       //初始化数组栈
    		top[i]=-1;
    	for(int i=0;i<r;i++)
    		for(int j=0;j<c;j++)
    			Graph[i][j]=' ';
    }
    public void show(){                            //展示棋盘
    	for(int i=row-1;i>=0;i--){
    		System.out.print("|");
    		for(int j=0;j<column;j++)
    			System.out.print(Graph[i][j]+"|");
    		System.out.println();
    	}
    }
    public  int Input(int y,int key){              //下棋
    	if(y>=column||y<0||top[y]==row-1){
    		System.out.println("out of range");
    		return 1;
    	}
    	Graph[++top[y]][y]=C[key%2].toUpperCase().charAt(0);
    	empty--;
    	return 0;
    }
	public int judge(int x,int y) {                //判断是否有人胜出
		if (search(Graph[x][y], x, y, 1,  0) + search(Graph[x][y], x, y, -1,  0) == 3|| //水平探测
		    search(Graph[x][y], x, y, 1,  1) + search(Graph[x][y], x, y, -1, -1) == 3|| //对角探测
		    search(Graph[x][y], x, y, 0,  1) + search(Graph[x][y], x, y,  0, -1) == 3|| //垂直探测
		    search(Graph[x][y], x, y, 1, -1) + search(Graph[x][y], x, y, -1,  1) == 3)  //对角探测
			return 1;
		return 0;                          //未有人获胜
	}
  	public int search(char k, int a, int b, int z, int f) {    //单向探测函数
		a += z;	b += f;
		if (b >= column || a >= row || a < 0 || b < 0||Graph[a][b] != k)
			return 0;
		return search(k, a , b , z, f)+1;
	}
    public static void main(String[] args) {
		JavaGame My=new JavaGame(6,7);
		Scanner input=new Scanner(System.in);
		int tmp,key;
		My.show();
		for(int i=0;;){
			System.out.print("Drop a "+My.C[i%2]+" disk at column(0-6) : ");
			tmp=input.nextInt();
			if(My.Input(tmp,i)!=0)      //出错后 执行下一循环(i没有++)
				continue;
			My.show();
			if(My.judge(My.top[tmp],tmp)==1){	//判断是否有人胜出
				System.out.println("The "+My.C[i%2]+" player won");
				break;
			}
			if(My.empty==0){					//平局
				System.out.println("Chess draw");
				break;
			}
			i++;
		}
    }
}

C++(第1版,有点乱):

judge:非递归(java也可用):双向探测

#include<iostream>
#include<string>
using namespace std;
class Chess {
public:
	Chess();                   //初始化成员数据
	void show();               //显示棋盘
	int input(int y,int key);  //下棋
	int judge(int y);          //判断结果
	string C[2] = { "red","yellow" };
private:
	string Graph[6][7];
	int top[7];             //模拟栈
};
Chess::Chess(){
	memset(top, -1, sizeof(top));     //数组top初始化为-1
	for (int i = 0; i < 6; i++) {     //初始化Graph
		for (int j = 0; j < 7; j++) {
			Graph[i][j] = " ";  
		}
	}
}
void Chess::show(){
	for (int i = 5; i >= 0; i--) {
		cout << "|";
		for (int j = 0; j < 7; j++) 
			cout << Graph[i][j] << "|";
		cout << endl;
	}
}
int Chess::input(int y,int key) {
	if (y > 6 || y < 0){      //越界检测
		cout << "y is out of range[0,6]" << endl;
		return 1;
	}
	if (top[y] == 5) {
		cout << "x is out of range" << endl;
		return 1;
	}
	Graph[++top[y]][y] = toupper(C[key % 2][0]);    //赋值操作
	return 0;
}
int Chess::judge(int y) {

	int kx[4] = { 0, 1, 1, 1 },      //八个方向(4个正方向,另外4个负方向取反)
		ky[4] = { 1, 1, 0,-1 };
	int a, b, count = 0;
	int x = top[y];
	for (int i = 0; i < 4; i++) {          //八个方向检测
		a = x;          //数据初始化
		b = y;
		count = 0;
		for (int j = 0; j < 3; j++) {      //检测四个正方向
			a += kx[i];
			b += ky[i];
			if (b > 6 || a > 5 || a < 0 || b < 0 || Graph[a][b] == " ")        //边界检测
				break;
			if (Graph[a][b] == Graph[x][y] )
				count++;
		}
		a = x;
		b = y;
		for (int j = 0; j < 3; j++) {      //检测四个负方向
			a -= kx[i];
			b -= ky[i];
			if (b > 6 || a > 5 || a < 0 || b < 0 || Graph[a][b] == " ")        //边界检测
				break;
			if (Graph[a][b] == Graph[x][y])       //逻辑判断
				count++;
		}
		if (count == 3)                 //四子相连,此人胜出
			return 1;
	}
	for (int i = 0; i < 7; i++) {       //只要有一列未满,返回0
		if (top[i] != 5)           
			return 0;
	}
	return -1;                          //全满,返回-1(平局)
}
int main() {
	Chess myChess;
	myChess.show();
	int tmp,key;
	for (int i = 0;;) {         //i奇偶决定颜色
		cout << "Drop a "<< myChess.C[i % 2] <<" disk at column(0-6): ";
		cin >> tmp;
		if (myChess.input(tmp, i))    //bug检测
			continue;
		system("cls");          //清屏
		myChess.show();
		key = myChess.judge(tmp);   //key判断输赢,平局
		if (key==1) {
			cout << "The " << myChess.C[i % 2] << " player won" << endl;
			break;
		}
		else if (key == -1) {
			cout << "Chess draw" << endl;
			break;
		}
		i++;
	}
return 0;
}

 

posted on 2018-09-29 01:03  氵丨  阅读(783)  评论(0编辑  收藏  举报