fork download
  1. module main;
  2.  
  3. import std.stdio;
  4. import std.random;
  5. import std.process;
  6. import core.thread;
  7.  
  8. class Tetris
  9. {
  10. private BlockMap fb;
  11. private ControlBlock cb;
  12. private size_t _cbx;
  13. private size_t _cby;
  14. private int fallCount;
  15. public bool fastFall;
  16. private Random r;
  17. private bool _gameover;
  18.  
  19. public @property const(BlockMap) fieldBlock(){ return cast(const(BlockMap))fb; }
  20. public @property const(BlockMap) controlBlock(){ return cast(const(BlockMap))cb; }
  21. public @property size_t cbx(){ return _cbx; }
  22. public @property size_t cby(){ return _cby; }
  23. public @property bool gameovar(){ return _gameover; }
  24.  
  25. public this()
  26. {
  27. this.fb = new BlockMap(10, 24);
  28. this.r.seed(unpredictableSeed);
  29. }
  30.  
  31. public void forwardTime()
  32. {
  33. if(_gameover == true) return;
  34. fallCount++;
  35. if(fallCount >= (fastFall ? 1 : 10))
  36. {
  37. fall();
  38. fallCount = 0;
  39. }
  40. if(cb is null)
  41. {
  42. lineBreak();
  43. setControlBlock();
  44. }
  45. }
  46.  
  47. private void lineBreak()
  48. {
  49. x: foreach(size_t x; 0..fb.x)
  50. {
  51. foreach(size_t y; 0..fb.y)
  52. {
  53. if(fb[x, y] == false) continue x;
  54. }
  55. foreach(size_t y; 0..fb.y)
  56. {
  57. fb[x, y] = false;
  58. }
  59. }
  60. }
  61.  
  62. private void setControlBlock()
  63. {
  64. cb = ControlBlock.basicOminoFactory(r.front());
  65. _cbx = fb.x / 2 - cb.x / 2;
  66. _cby = 4 - cb.y;
  67. _gameover = collideJudge();
  68. }
  69.  
  70. private void fix()
  71. {
  72. foreach(size_t x; 0..cb.x)
  73. {
  74. foreach(size_t y; 0..cb.y)
  75. {
  76. if(cb[x, y] == true) fb[_cbx + x, _cby + y] = true;
  77. }
  78. }
  79. cb = null;
  80. }
  81.  
  82. private bool collideJudge()
  83. {
  84. foreach(size_t x; 0..cb.x)
  85. {
  86. foreach(size_t y; 0..cb.y)
  87. {
  88. if(_cbx + x < 0 || _cbx + x >= fb.x || _cby + y < 0 || _cby + y >= fb.y) return true;
  89. if(cb[x, y] == true && fb[_cbx + x, _cby + y] == true) return true;
  90. }
  91. }
  92. return false;
  93. }
  94.  
  95. private void fall()
  96. {
  97. _cby++;
  98. if(collideJudge == true)
  99. {
  100. _cby--;
  101. fix();
  102. }
  103. }
  104.  
  105. public void rightMove()
  106. {
  107. _cbx++;
  108. if(collideJudge == true) _cbx--;
  109. }
  110.  
  111. public void leftMove()
  112. {
  113. _cbx--;
  114. if(collideJudge == true) _cbx++;
  115. }
  116.  
  117. public void rightTurn()
  118. {
  119. cb.rightTurn();
  120. if(collideJudge == true) cb.leftTurn();
  121. }
  122.  
  123. public void leftTurn()
  124. {
  125. cb.leftTurn();
  126. if(collideJudge == true) cb.rightTurn();
  127. }
  128. }
  129.  
  130. class BlockMap
  131. {
  132. public const size_t x;
  133. public const size_t y;
  134. private bool[] bm;
  135.  
  136. public this(size_t x, size_t y, bool[][] bm = null)
  137. {
  138. this.x = x;
  139. this.y = y;
  140. this.bm = new bool[x * y];
  141.  
  142. if(bm !is null)
  143. {
  144. foreach(size_t ix; 0..bm.length)
  145. {
  146. foreach(size_t iy; 0..bm[ix].length)
  147. {
  148. this[ix, iy] = bm[ix][iy];
  149. }
  150. }
  151. }
  152. }
  153.  
  154. public bool opIndexAssign(bool value, size_t x, size_t y)
  155. {
  156. return bm[this.y * x + y] = value;
  157. }
  158.  
  159. public bool opIndex(size_t x, size_t y) const
  160. {
  161. return bm[this.y * x + y];
  162. }
  163. }
  164.  
  165. class ControlBlock
  166. {
  167. private BlockMap[] cbList;
  168. private size_t index;
  169.  
  170. public this(BlockMap[] cbList...)
  171. {
  172. this.cbList = cbList;
  173. }
  174.  
  175. alias presentControlBlock this;
  176. public @property BlockMap presentControlBlock()
  177. {
  178. return cbList[index];
  179. }
  180.  
  181. public void rightTurn()
  182. {
  183. index++;
  184. if(index >= cbList.length) index = 0;
  185. }
  186.  
  187. public void leftTurn()
  188. {
  189. index--;
  190. if(index < 0) index = cbList.length;
  191. }
  192.  
  193. public static ControlBlock basicOminoFactory(int index)
  194. {
  195. BlockMap[] bmList;
  196. final switch(index % 1)
  197. {
  198. case 0:
  199. bmList = new BlockMap[2];
  200. bmList[0] = new BlockMap(4, 4, [[0,0,1,0],[0,0,1,0],[0,0,1,0],[0,0,1,0]]);
  201. bmList[1] = new BlockMap(4, 4, [[0,0,0,0],[1,1,1,1],[0,0,0,0],[0,0,0,0]]);
  202. break;
  203. }
  204. return new ControlBlock(bmList);
  205. }
  206. }
  207.  
  208. class ConsoleUI
  209. {
  210. public Tetris t;
  211.  
  212. public void show()
  213. {
  214. char[] str;
  215. str ~= "\f";
  216. foreach(size_t y; 0..t.fieldBlock.y)
  217. {
  218. foreach(size_t x; 0..t.fieldBlock.x)
  219. {
  220. size_t cbx = x - t.cbx;
  221. size_t cby = y - t.cby;
  222. size_t cbxt = t.controlBlock.x;
  223. size_t cbyt = t.controlBlock.y;
  224. if(t.fieldBlock[x, y] == true)
  225. {
  226. str ~= "[]";
  227. }
  228. else if(!(cbx < 0 || cbx >= cbxt || cby < 0 || cby >= cbyt) && t.controlBlock[cbx, cby] == true)
  229. {
  230. str ~= "[]";
  231. }
  232. else
  233. {
  234. str ~= " ";
  235. }
  236. }
  237. str ~= "\n";
  238. }
  239. stdout.rawWrite(str);
  240. }
  241. }
  242.  
  243. void main()
  244. {
  245. ConsoleUI cui = new ConsoleUI();
  246. cui.t = new Tetris();
  247. while(true)
  248. {
  249. cui.t.forwardTime();
  250. cui.show();
  251. if(cui.t.gameovar == true) break;
  252. Thread.sleep(1000000);
  253. }
  254. }
  255.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty