码迷,mamicode.com
首页 > 其他好文 > 详细

[Practice]山寨2048之Terminal版

时间:2014-05-09 02:34:59      阅读:442      评论:0      收藏:0      [点我收藏+]

标签:2048   c++   terminal   

吹水:

今日得闲没野做,就捻着搵点野料下。

我玩过2048,觉得规则挺简单的,应该挺好入手的。

毕竟,也是开源的。网上也存在很多教材或自定义,神马的。

于是,我本着尝试的态度,不看教程,能否山寨一个出来。


分析:去官网http://gabrielecirulli.github.io/2048/玩上几盘,一步一步地摸索其规则。

最后,经过一个下午和傍晚的时间,我实现了大致的功能,也不清楚是否和原版100%相同。

而且程序效率也不高,在此就不详解我自己的做法了。有兴趣的人,可自行参照网上的教程。

此帖,自娱自乐,目的只有一个:锻炼自己的编码能力和分析步骤。


备注:控制台版,使用C++语言


Grid.h

/***************************************************************
 *程序名称:2048
 *内容摘要:练习
 *其它说明:无
 *当前版本:V1.0
 *作    者:tbz
 *完成日期:2014年5月8日
 ***************************************************************/

#ifndef _GIRD_H_
#define _GIRD_H_

//实现4X4的方格,并提供移动、检测输赢等操作
class Grid
{
public:
	explicit Grid();
	
	void print();

	void move(char action);
	
	bool isWon();
	bool isLost();

private:
	int position[4][4];

	//这四个函数原理一致
	bool moveLeft();
	bool moveRight();
	bool moveUp();
	bool moveDown();
	
	//辅助函数
	bool isExistEqual(int row, int column);
	void generateEntry(int count);
	int& at(int row, int column);
	int random(int min, int max);
};

#endif

Grid.cpp

/***************************************************************
 *程序名称:2048
 *内容摘要:练习
 *其它说明:无
 *当前版本:V1.0
 *作    者:tbz
 *完成日期:2014年5月8日
 ***************************************************************/

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include "Grid.h"
using namespace std;

//从1开始计数
int& Grid::at(int row, int column)
{
	return position[row-1][column-1];
}

//生成某范围的随机数
int Grid::random(int min, int max)
{
	return ((rand() % (max-min+1)) + min);
}

//建立4X4表格,并初始化
Grid::Grid()
{
	srand(time(0));
	for (int row = 1; row <= 4; ++row)
		for (int column = 1; column <= 4; ++column)
		{
			at(row, column) = 0;	
		}	

	//放置2个数
	generateEntry(2);
}

//生成几个数,不重复
void Grid::generateEntry(int count)
{
	int x = 0, y = 0, value = 0;
	for (int i = 0; i < count; ++i)
	{
		bool valid = false;
		while(!valid)
		{
			x = random(1, 4);
			y = random(1, 4);
			value = random(1, 2) * 2;
			if (!at(x, y))	
			{
				valid = true;
				at(x, y) = value;
			}
		}
	}
}

//视图绘制
void Grid::print()
{
	cout << " ------------2048------------" << endl;
	cout << " ____________________________" << endl;
	for (int i = 1; i <= 4; ++i)
	{
		cout << "|";
		for (int j = 1; j <= 4; ++j)
		{
			int temp = at(i, j);
			if (temp)
				cout << " " << setw(4) << temp << ". ";
			else
				cout << " " << setw(4) << ‘ ‘ << ". ";
		}

		cout << "|" << endl;
	}
	cout << " ----------------------------" << endl;
}

void Grid::move(char action)
{
	bool moved = false;
	switch(action)
	{
		case ‘a‘:
		case ‘A‘:
			moved = moveLeft();
			break;
		case ‘d‘:
		case ‘D‘:
			moved = moveRight();
			break;
		case ‘w‘:
		case ‘W‘:
			moved = moveUp();
			break;
		case ‘s‘:
		case ‘S‘:
			moved = moveDown();
			break;
	}
	if (moved)
		generateEntry(1);
}

//检测
bool Grid::isWon()
{
	for (int i = 1; i <= 4; ++i)
	{
		for (int j = 1; j <= 4; ++j)
		{
			if (at(i, j) == 2048)
				return true;
		}
	}
	return false;
}

bool Grid::isExistEqual(int row, int column)
{
	bool ret = false;

	//行检测
	if (row == 1)
	{
		ret = (at(row, column) == at(row+1, column));
	}
	else if (row == 4)
	{
		ret = (at(row, column) == at(row-1, column));
	}
	else
	{
		ret = (at(row, column) == at(row-1, column)) && (at(row, column) == at(row+1, column));
	}

	//列检测
	if (column == 1)
	{
		ret = (at(row, column) == at(row, column+1));
	}
	else if (column == 4)
	{
		ret = (at(row, column) == at(row, column-1));
	}
	else
	{
		ret = (at(row, column) == at(row, column-1)) && (at(row, column) == at(row, column+1));
	}
	return ret;
}

bool Grid::isLost()
{
	for (int i = 1; i <= 4; ++i)
	{
		for (int j = 1; j <= 4; ++j)
		{
			if (!at(i, j))
				return false;
			else
			{
				if (isExistEqual(i, j))
					return false;
			}
		}
	}

	return true;
}

//下
bool Grid::moveDown()
{
	int top = 1, bottom = 4;
	bool moved = false;

	for (int column = 1; column <= 4; ++column)
	{
		//相同的数字合并
		int last = 0, pos = 0;
		for (int work = bottom; work >= top; --work)
		{
			if (at(work, column))
			{
				if (last)
					if (at(work, column) == last)
					{
						at(work, column) = 0;
						at(pos, column) *= 2;
						moved = true;
						last = 0;
						pos = 0;
					}
					else
					{
						last = at(work, column);
						pos = work;
					}
				else if (!last)
				{
					last = at(work, column);
					pos = work;
				}
			}
		}

		//将数字往栈底挤
		for (int work = bottom; work >= top; --work)
		{
			if (at(work, column))
			{
				for (int i = work; i <= bottom-1; ++i)
				{
					if (!at(i+1, column))
					{
						swap(at(i, column), at(i+1, column));
						moved = true;
					}
					else break;
				}
			}
		}
	}

	return moved;
}

//上
bool Grid::moveUp()
{
	int top = 4, bottom = 1;
	bool moved = false;

	for (int column = 1; column <= 4; ++column)
	{
		//相同的数字合并
		int last = 0, pos = 0;
		for (int work = bottom; work <= top; ++work)
		{
			if (at(work, column))
			{
				if (last)
					if (at(work, column) == last)
					{
						at(work, column) = 0;
						at(pos, column) *= 2;
						moved = true;
						last = 0;
						pos = 0;
					}
					else
					{
						last = at(work, column);
						pos = work;
					}
				else if (!last)
				{
					last = at(work, column);
					pos = work;
				}
			}
		}

		//将数字往底挤
		for (int work = bottom; work <= top; ++work)
		{
			if (at(work, column))
			{
				for (int i = work; i >= bottom+1; --i)
				{
					if (!at(i-1, column))
					{
						swap(at(i, column), at(i-1, column));
						moved = true;
					}
					else break;
				}
			}
		}
	}

	return moved;
}

//左
bool Grid::moveLeft()
{
	int top = 4, bottom = 1;
	bool moved = false;

	for (int row = 1; row <= 4; ++row)
	{
		//相同的数字合并
		int last = 0, pos = 0;
		for (int work = bottom; work <= top; ++work)
		{
			if (at(row, work))
			{
				if (last)
					if (at(row, work) == last)
					{
						at(row, work) = 0;
						at(row,pos) *= 2;
						moved = true;
						last = 0;
						pos = 0;
					}
					else
					{
						last = at(row, work);
						pos = work;
					}
				else if (!last)
				{
					last = at(row, work);
					pos = work;
				}
			}
		}

		//将数字往底挤
		for (int work = bottom; work <= top; ++work)
		{
			if (at(row, work))
			{
				for (int i = work; i >= bottom+1; --i)
				{
					if (!at(row, i-1))
					{
						swap(at(row, i), at(row, i-1));
						moved = true;
					}
					else break;
				}
			}
		}
	}

	return moved;
}


//右
bool Grid::moveRight()
{
	int top = 1, bottom = 4;
	bool moved = false;

	for (int row = 1; row <= 4; ++row)
	{
		//相同的数字合并
		int last = 0, pos = 0;
		for (int work = bottom; work >= top; --work)
		{
			if (at(row, work))
			{
				if (last)
					if (at(row, work) == last)
					{
						at(row, work) = 0;
						at(row,pos) *= 2;
						moved = true;
						last = 0;
						pos = 0;
					}
					else
					{
						last = at(row, work);
						pos = work;
					}
				else if (!last)
				{
					last = at(row, work);
					pos = work;
				}
			}
		}

		//将数字往底挤
		for (int work = bottom; work >= top; --work)
		{
			if (at(row, work))
			{
				for (int i = work; i <= bottom-1; ++i)
				{
					if (!at(row, i+1))
					{
						swap(at(row, i), at(row, i+1));
						moved = true;
					}
					else break;
				}
			}
		}
	}

	return moved;
}

main.cpp


/***************************************************************
 *程序名称:2048
 *内容摘要:练习
 *其它说明:无
 *当前版本:V1.0
 *作    者:tbz
 *完成日期:2014年5月8日
 ***************************************************************/

#include <cstdlib>
#include <conio.h>
#include "Grid.h"
#include <iostream>
using namespace std;

bool isNeed(char c)
{
	switch (c)
	{
		case ‘a‘:case ‘s‘:case ‘d‘:case ‘w‘:
		case ‘A‘:case ‘S‘:case ‘D‘:case ‘W‘:
			return true;
	}
	return false;
}

int main(int argc, char const *argv[])
{
	Grid game;

	//game flow control
	while (true)
	{
		system("cls");
		game.print();
		if (game.isWon())
		{
			cout << endl << "Congratulation!	You won!" << endl;
			cout << "Press any key to exit." << endl;
			getch();
			return 0;
		}

		if (game.isLost())
			break;

		//Promt
		cout << endl;
		cout << "A -> Left, D -> Right, W -> Up, S -> Down. (K -> Exit)" << endl;
		char input = getch();

		if (input == ‘k‘)
			return 0;
		if (!isNeed(input))	continue;
		
		game.move(input);
	}

	cout << "Sorry! You lose." << endl;
	getch();
	return 0;
}

总结:

分析很重要。

每开发一个独立功能,就测试一下,可减少后期调试的痛苦。

[Practice]山寨2048之Terminal版,布布扣,bubuko.com

[Practice]山寨2048之Terminal版

标签:2048   c++   terminal   

原文地址:http://blog.csdn.net/tbz888/article/details/25335555

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!