汉诺塔游戏的C++实现

昨天没事在用别人的文曲星查字!突然看到那个汉诺塔游戏…..

反正这两天刚好手有点痒,于是就有了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
#ifndef  HANIO_H_
#define HANIO_H
class Stack
{
private:
enum{ MAX=50 };
int m_node[MAX];
int m_top;
int m_size;
int m_index;
public:
Stack();
~Stack() { };
bool Isfull() { return m_top==MAX-1 ;}; //堆栈满则返回TRUE
bool Isempty() { return m_top==-1;}; //堆栈空则返回TRUE
int Top() { return m_top; };
int TopValue() { return m_node[m_top];};
int GetDataFromIndex(int i) { return m_node[i]; };
int GetIndex() { return m_index; } ;
void SetIndex(int index) { m_index = index; };
int Size() { return m_top+1; };

bool Push(int data);
bool Pop(int * pData);
int MoveToNext();
void OutPrint();

};

class Hanio
{
Stack m_stack[3];
int m_num; //盘数
int m_steps; //移动次数
int m_times; //完成所用时间
void print(char ch,int n);
public:
Hanio(int num=3);
~Hanio() {};
void GameStart();
bool MoveFromTo(int x,int y); //从x号盘移动到y号盘
void DrawPaletes(char ch='*'); //打印3个堆的盘子
bool IsFinished() ; //结束返回TURE;

int Solve(char from,char to,char auxiliary,int n); //求解其解法路径
};

#endif
//hanio.cpp
#include "hanio.h"
#include <iostream>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<windows.h>
Stack::Stack()
{
m_top=-1;
m_index=m_top;
for(int i=0;i<MAX;i++)
m_node[i]=0;
}
bool Stack::Push(int data)
{
if(Isfull())
return false;
m_top++;
m_node[m_top]=data;
m_index=m_top;
return true;
}
bool Stack::Pop(int *pData)
{
if(Isempty())
return false;
*pData=m_node[m_top];
m_node[m_top]=0;
m_top--;
m_index=m_top;
return true;
}
int Stack::MoveToNext()
{
int temp=m_index;
m_index--;
return m_node[temp];
}
void Stack::OutPrint()
{
if(m_top!=-1)
{
for(int i=0;i<=m_top;i++)
std::cout<<"["<<m_node[i]<<"]";
}
}


///////////////////////////////////////
Hanio::Hanio(int num)
{
m_num=num;
m_steps=0;
m_times=0;
for(int i=num;i>=1;i--)
m_stack[0].Push(i);
//m_stack[0].OutPrint();
}
void Hanio::print(char ch,int n)
{
for(int i=1;i<=n;i++)
std::cout<<ch;
}
void Hanio::DrawPaletes(char ch)
{
int max;
max=m_stack[0].Size()>m_stack[1].Size() ? m_stack[0].Size() : m_stack[1].Size();
max=m_stack[2].Size()>max ? m_stack[2].Size() : max;

//std::cout<<"Max:"<<max<<std::endl;
m_stack[0].SetIndex(max-1);
m_stack[1].SetIndex(max-1);
m_stack[2].SetIndex(max-1);

for(int i=1;i<=max;i++)
{
int data1=m_stack[0].MoveToNext();
int data2=m_stack[1].MoveToNext();
int data3=m_stack[2].MoveToNext();
if(data1==0)
print(' ',20);
else
{
print(' ',10-data1);
print(ch,2*data1);
print(' ',10-data1);
}

if(data2==0)
print(' ',20);
else
{
print(' ',10-data2);
print(ch,2*data2);
print(' ',10-data2);
}

if(data3==0)
print(' ',20);
else
{
print(' ',10-data3);
print(ch,2*data3);
print(' ',10-data1);
}
std::cout<<std::endl;
}

}

bool Hanio::MoveFromTo(int x,int y)
{
m_steps++; //计算所走的步数
if(m_stack[x].Isempty())
{
std::cout<<x<<" pallete is empty ! continue !"<<std::endl;
std::cin.get();
return false;
}

if(m_stack[y].Isempty())
{
int data;
m_stack[x].Pop(&data);
m_stack[y].Push(data);
return true;
}
else
{
if(m_stack[x].TopValue()>m_stack[y].TopValue())
{
std::cout<<"The board can't move from "<<x<<" plate to " <<y<<" plate!"<<std::endl;
std::cin.get();
return false;
}
else
{
int data;
m_stack[x].Pop(&data);
m_stack[y].Push(data);
return true;
}
}
}
bool Hanio::IsFinished()
{
return m_stack[2].Top()==m_num-1;
}

void Hanio::GameStart()
{
using namespace std;
UINT StartTime=::GetTickCount();
UINT EndTime;
while(1)
{

system("cls");
print('-',80);
cout<<"steps: "<<m_steps; print(' ',20);
cout<<"Used time: "<<m_times<<endl;
print('-',80);
cout<<endl; cout<<endl; print(' ',10); cout<<"A";
print(' ',19); cout<<"B"; print(' ',19);
cout<<"C"<<endl<<endl;
Hanio::DrawPaletes();
cout<<endl; cout<<endl;
print('-',80);

//测试游戏是否结束
if(Hanio::IsFinished())
{
cout<<"你好强呀!从今天开始,维护世界和平的任务就交给你那!"<<endl;
cin.get();
break;
}
//输入命令并左相应的处理
char szCommand[50];
cout<<">>";
cin.getline(szCommand,50);
if(stricmp(szCommand,"QUIT")==0 || stricmp(szCommand,"Q")==0)
break;
if(stricmp(szCommand,"HELP")==0 || stricmp(szCommand,"H")==0)
{
cout<<" 本游戏说明 :"<<endl;
cout<<" 该游戏由DAVID用C++编程,花费了一个多下午的时间呢!!!,由命令行来控制铁饼的移动:"<<endl;
cout<<" QUIT / Q : 退出程序"<<endl;
cout<<" HELP / H : 查看该说明"<<endl;
cout<<" XY : X,Y的取值为A,B,C,意思时把X木桩最上面的铁饼移到Y木桩"<<endl;
cout<<" SOLVE / S : 显示求解该问题(移动铁饼)的最优路径..."<<endl;
cin.get();
}

char ch1=toupper(szCommand[0]);
char ch2=toupper(szCommand[1]);

if( ch1=='A' && ch2=='B')
Hanio::MoveFromTo(0,1);
else if ( ch1=='A' && ch2=='C')
MoveFromTo(0,2);
else if ( ch1=='B' && ch2=='A')
MoveFromTo(1,0);
else if ( ch1=='B' && ch2=='C')
MoveFromTo(1,2);
else if ( ch1=='C' && ch2=='A')
MoveFromTo(2,0);
else if ( ch1=='C' && ch2=='B')
MoveFromTo(2,1);
else
{
cout<<"Bad command !"<<endl;
cin.get();
}
//统计游戏所用时间
EndTime=GetTickCount();
m_times=(EndTime-StartTime)/1000;
}

}
int Hanio::Solve(char from,char to,char auxiliary,int n)
{
if(n==1)
return 0;
}
//main.cpp
#include<iostream>
#include"hanio.h"
#include<cstdlib>
using namespace std;
int StartPicture();//返回选择的盘数
int main()
{
int number;
number=StartPicture();
Hanio hanio(number);
hanio.GameStart();
return 0;
}

void print(char ch,int n)
{
for(int i=1;i<=n;i++)
std::cout<<ch;
}
int StartPicture()
{
using namespace std;
int number;
system("cls");
system("color fc");
print(' ',20);
print('-',25);
cout<<endl;
print(' ',20);
cout<<" Hanio(汉诺塔)"<<endl;
print(' ',20);
print('-',25);
cout<<endl;
print(' ',40);
print('-',5);
cout<<"By David"<<endl;
print('=',80);
cout<<" 相传在某一座古庙中有3根木桩,有24个铁盘由小到大放置在一根木柱上,庙中流传者一个传说:/"如果能把24个铁盘, 从一根木桩移动到另一个木桩,且必须遵守如下规则:"<<endl;
cout<<endl;
print(' ',5);cout<<"1. 每天只能动一个盘,而且只能从最上面的铁盘开始搬动."<<endl;
print(' ',5);cout<<"2. 必须维持较小的铁盘在上方的原则"<<endl;
cout<<endl;
cout<<"这两个原则,则当24个铁盘完全般到另一个木桩时,世界就回永久和平!!"<<endl;
cout<<"游戏的玩法可以在命令行中输入HELP查看"<<endl;
cout<<endl;cout<<endl;cout<<endl;cout<<endl;cout<<endl;
cout<<"再此输入你要搬的铁盘数(建议在1--10值间,太多回花费很长时间的)"<<endl;
print('=',80);
cout<<">>";
cin>>number;
cin.get();
system("cls");
return number;
}
David++