fork download
  1. // 2012-01-13T13:15+09:00
  2. // Cell.toggleLightとかCell.setStatusまわり、依存関係が逆だったので修正
  3.  
  4. import java.io.*;
  5. import java.util.*;
  6. import javax.swing.*;
  7. import java.awt.*;
  8. import java.awt.event.*;
  9.  
  10. // JavaDoc?なんですかそれは?(書式を学ぶのが面倒だなーと[おぃ])
  11.  
  12.  
  13. enum Status{
  14. BLANK,
  15. LIGHT,
  16. UNNUMBERED,
  17. NUMBERED
  18. }
  19.  
  20. // 位置情報をCellに持たせるか悩んだんだけど、やめた。それはCellの都合じゃなくてGameの都合のような気がしたから。
  21. // game.findCellPositionなんてのやgame.getCellとかがくっ付くし、Positionクラスなんてのを作る羽目になったけど…
  22.  
  23.  
  24. class Cell{
  25.  
  26. // そのセルの周囲に置けるライトの数だが、
  27. // 実際に置けないのではなく、
  28. // これは正解かどうかをチェックするルーチンで用いるつもりである。
  29.  
  30. // statusがStatus.NUMBEREDでないときは使われない。
  31.  
  32. private int maxlights;
  33.  
  34. // あまりマジックナンバーを使いたくなかったんで別に分けてる
  35. private Status status;
  36.  
  37. // 他のセルが変更された時、ボタンの背景色を変える必要があるんだけど
  38. // CellやGameはあくまでコア。JButtonのような、UIは関係ないので持たせたくなかった。
  39.  
  40. // 苦肉の策で、直接持たない代わりに、EventListenerインターフェースを実装したクラスに
  41. // 持たせることにした。(俺は不勉強なんですが、何かのデザインパターンにあったりします?)
  42.  
  43.  
  44.  
  45. // こういう「取り出すだけ、設定するだけのsetterやgetterは無駄。publicなメンバ変数だけでいいじゃん」という意見の人もいる。
  46. // 特に反対はしない。
  47.  
  48. public Status getStatus(){
  49. return status;
  50. }
  51.  
  52. public void setStatus(Status s){
  53. status = s;
  54. }
  55.  
  56. public int getMaxLights(){
  57. return maxlights;
  58. }
  59.  
  60. public void setMaxLights(int lights){
  61.  
  62. maxlights = lights;
  63. if(maxlightschangedlistener == null){
  64. return;
  65. }
  66. maxlightschangedlistener.maxLightsChanged(new MaxLightsChangedEvent(this,lights));
  67. }
  68.  
  69. // さっき出したListenerの話がこの辺。
  70.  
  71. LightToggledListener lighttoggledlistener;
  72. LightTogglingPropagatedListener lighttogglingpropagatedlistener;
  73. MaxLightsChangedListener maxlightschangedlistener;
  74.  
  75. public void addLightToggledListener(LightToggledListener listener){
  76. lighttoggledlistener = listener;
  77. }
  78.  
  79. public void addLightTogglingPropagatedListener(LightTogglingPropagatedListener listener){
  80. lighttogglingpropagatedlistener = listener;
  81. }
  82. public void addMaxLightsChangedListener(MaxLightsChangedListener listener){
  83. maxlightschangedlistener = listener;
  84. }
  85.  
  86. public void propagateLightToggling(Status s){
  87. if(lighttogglingpropagatedlistener == null){
  88. return;
  89. }
  90. lighttogglingpropagatedlistener.lightTogglingPropagated(new LightTogglingPropagatedEvent(this,s));
  91. }
  92.  
  93. public void toggleLight(Status s){
  94. if(lighttoggledlistener == null){
  95. return;
  96. }
  97. lighttoggledlistener.lightToggled(new LightToggledEvent(this,s));
  98.  
  99. }
  100.  
  101. }
  102.  
  103. interface LightToggledListener extends java.util.EventListener{
  104. public void lightToggled(LightToggledEvent ev);
  105. }
  106.  
  107. class LightToggledEvent extends EventObject{
  108. Status status;
  109. public LightToggledEvent(Object source,Status s){
  110. super(source);
  111. status = s;
  112. }
  113.  
  114. public Status getStatus(){
  115. return status;
  116. }
  117. }
  118.  
  119.  
  120. interface LightTogglingPropagatedListener extends java.util.EventListener{
  121. public void lightTogglingPropagated(LightTogglingPropagatedEvent ev);
  122. }
  123.  
  124. class LightTogglingPropagatedEvent extends EventObject{
  125. Status status;
  126. public LightTogglingPropagatedEvent(Object source,Status s){
  127. super(source);
  128. status = s;
  129. }
  130.  
  131. public Status getStatus(){
  132. return status;
  133. }
  134. }
  135.  
  136. interface MaxLightsChangedListener extends java.util.EventListener{
  137. public void maxLightsChanged(MaxLightsChangedEvent ev);
  138. }
  139.  
  140. class MaxLightsChangedEvent extends EventObject{
  141. int maxlights;
  142. public MaxLightsChangedEvent(Object source,int maxlights1){
  143. super(source);
  144. maxlights = maxlights1;
  145. }
  146. public int getMaxLights(){
  147. return maxlights;
  148. }
  149. }
  150.  
  151. // あまり好きじゃない。
  152.  
  153. class Position{
  154. private int row;
  155. private int col;
  156. public Position(int row1,int col1){
  157. row = row1;
  158. col = col1;
  159. }
  160. public int getRow(){
  161. return row;
  162. }
  163. public int getColumn(){
  164. return col;
  165. }
  166.  
  167. }
  168. //これも正直苦肉の策
  169.  
  170. class CellInitializationData{
  171. Position position;
  172. Status status;
  173. int maxlights;
  174. CellInitializationData(int row,int col,int lights){
  175. position = new Position(row,col);
  176. if(lights < -1){
  177. }
  178. if(lights == -1){
  179. status = Status.UNNUMBERED;
  180. return;
  181. }
  182. status = Status.NUMBERED;
  183. maxlights = lights;
  184.  
  185. }
  186.  
  187. public int getMaxLights(){
  188. return maxlights;
  189. }
  190.  
  191. public Status getStatus(){
  192. return status;
  193. }
  194.  
  195. public Position getPosition(){
  196. return position;
  197. }
  198. }
  199.  
  200. // 初期配置データ読み込み用クラス。まぁGameクラスに統合しても良かったけどね。
  201.  
  202. class GameDataReader{
  203.  
  204. public static java.util.List<CellInitializationData> ReadData(BufferedReader reader) throws IOException{
  205. java.util.List<CellInitializationData> list = new ArrayList<CellInitializationData>();
  206.  
  207. while (true){
  208. int row;
  209. int col;
  210. int lights;
  211. String emptyline;
  212.  
  213. row = Integer.parseInt(reader.readLine());
  214. col = Integer.parseInt(reader.readLine());
  215. lights = Integer.parseInt(reader.readLine());
  216.  
  217. list.add(new CellInitializationData(row,col,lights));
  218. if(reader.readLine() == null){
  219. break;
  220. }
  221.  
  222. }
  223. return list;
  224. }
  225. }
  226.  
  227. // ゲーム本体
  228.  
  229. class Game
  230. {
  231. private Cell cells[][] = null;
  232.  
  233. // 初期配置のために第一引数を持たせる予定。でも、設計があまりよくならなそうなんだよなあ。どうしようかなあ。
  234.  
  235. public Game(int rows,int cols){
  236. cells= new Cell[rows][cols];
  237. for(int i = 0;i < rows;i++){
  238. for(int j = 0;j < cols;j++){
  239. cells[i][j] = new Cell();
  240. }
  241. }
  242.  
  243. }
  244.  
  245. public void Initialize(java.util.List<CellInitializationData> list){
  246. for(int i = 0;i < cells.length;i++){
  247. for(int j = 0;j < cells[i].length;j++){
  248. Cell c = cells[i][j];
  249. c.setStatus(Status.BLANK);
  250. c.toggleLight(Status.BLANK);
  251. }
  252. }
  253. for(CellInitializationData ci:list){
  254. Cell c = cells[ci.getPosition().getRow()][ci.getPosition().getColumn()];
  255. c.setStatus(ci.getStatus());
  256. c.setMaxLights(ci.getMaxLights());
  257.  
  258. }
  259. }
  260.  
  261. public boolean toggleLight(int row,int col){
  262. if(cells[row][col].getStatus() == Status.NUMBERED){
  263. return false;
  264. }
  265. if(cells[row][col].getStatus() == Status.UNNUMBERED){
  266. return false;
  267. }
  268. java.util.List<Cell> list = getLightingArea(row,col);
  269. if(list == null){
  270. return false;
  271. }
  272. if(cells[row][col].getStatus() == Status.BLANK){
  273. cells[row][col].setStatus(Status.LIGHT);
  274. cells[row][col].toggleLight(Status.LIGHT);
  275. for(Cell c:list){
  276. c.propagateLightToggling(Status.LIGHT);
  277. }
  278. }else if(cells[row][col].getStatus() == Status.LIGHT){
  279. cells[row][col].setStatus(Status.BLANK);
  280. cells[row][col].toggleLight(Status.BLANK);
  281.  
  282. for(Cell c:list){
  283. Position p = findCellPosition(c);
  284. // その場所にライトが置ける => その場所はそのライトのみによって照らされていた場所
  285. if(getLightingArea(p.getRow(),p.getColumn()) != null){
  286. c.propagateLightToggling(Status.BLANK);
  287. }
  288. }
  289. }
  290.  
  291.  
  292. return true;
  293. }
  294.  
  295. // 指定された位置にライトを置いたときにそのライトによって照らされる範囲を返す。
  296. // 指定された位置が既に他のライトによって照らされているときはnullを返す。(要素数0のリストのほうがいいだろうか?)
  297. private java.util.List<Cell> getLightingArea(int row,int col){
  298. java.util.List<Cell> list = new ArrayList<Cell>();
  299. for(int i = row-1;i >= 0;i--){
  300. if(cells[i][col].getStatus() == Status.LIGHT){
  301. return null;
  302. }
  303. if(cells[i][col].getStatus() != Status.BLANK){
  304. break;
  305. }
  306. list.add(cells[i][col]);
  307. }
  308. for(int i = row+1;i < cells.length ;i++){
  309. if(cells[i][col].getStatus() == Status.LIGHT){
  310. return null;
  311. }
  312. if(cells[i][col].getStatus() != Status.BLANK){
  313. break;
  314. }
  315. list.add(cells[i][col]);
  316. }
  317. for(int i = col-1;i >= 0;i--){
  318. if(cells[row][i].getStatus() == Status.LIGHT){
  319. return null;
  320. }
  321. if(cells[row][i].getStatus() != Status.BLANK){
  322. break;
  323. }
  324. list.add(cells[row][i]);
  325. }
  326. for(int i = col+1;i < cells[0].length;i++){
  327. if(cells[row][i].getStatus() == Status.LIGHT){
  328. return null;
  329. }
  330. if(cells[row][i].getStatus() != Status.BLANK){
  331. break;
  332. }
  333. list.add(cells[row][i]);
  334. }
  335. //list.add(cells[row][col]);
  336.  
  337. return list;
  338. }
  339.  
  340. public Position findCellPosition(Cell c){
  341. for(int i = 0;i < cells.length ;i++){
  342. for(int j = 0;j < cells[i].length ;j++){
  343. if(cells[i][j] == c){
  344. Position retval = new Position(i,j);
  345. return retval;
  346. }
  347.  
  348. }
  349.  
  350. }
  351. }
  352.  
  353. public Cell getCell(int row,int col){
  354. return cells[row][col];
  355. }
  356.  
  357.  
  358. }
  359.  
  360. //ここまでCore
  361.  
  362. //ここからUI
  363.  
  364. // 名前は悩んでます。
  365.  
  366. class Form1 extends JFrame implements ActionListener{
  367.  
  368. JPanel panel;
  369.  
  370. Game game;
  371.  
  372. CellButton[][] buttons;
  373.  
  374. public Form1() throws IOException{
  375.  
  376. game = new Game(10,10);
  377.  
  378. setTitle("美術館パズル");
  379. setSize(800,600);
  380. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  381. setResizable(false);
  382.  
  383. panel = new JPanel();
  384. add(panel);
  385.  
  386. panel.setLayout(new GridLayout(10,10));
  387.  
  388. buttons = new CellButton[10][10];
  389.  
  390. for(int i=0; i<10; i++) {
  391. for(int j=0; j<10; j++) {
  392. buttons[i][j] = new CellButton(game.getCell(i,j));
  393. buttons[i][j].addActionListener(this);
  394. panel.add(buttons[i][j]);
  395. }
  396. }
  397.  
  398. game.Initialize(GameDataReader.ReadData(new BufferedReader(new InputStreamReader(System.in))));
  399. }
  400.  
  401. //コアとUIを繋いでいる。MVCモデルとかあまり学んでないけどCにあたるのかなあ?
  402.  
  403. public void actionPerformed(ActionEvent ae) {
  404. CellButton button = (CellButton)ae.getSource();
  405. Position p = game.findCellPosition(button.getCell());
  406. game.toggleLight(p.getRow(),p.getColumn());
  407. }
  408. }
  409.  
  410.  
  411. class CellButton extends JButton{
  412. Cell c;
  413. public CellButton(Cell c1){
  414. c = c1;
  415. c.addLightToggledListener(new ButtonCellLightToggledListener(this));
  416. c.addLightTogglingPropagatedListener(new ButtonCellLightTogglingPropagatedListener(this));
  417. c.addMaxLightsChangedListener(new ButtonCellMaxLightsChangedListener(this));
  418. }
  419.  
  420. public Cell getCell(){
  421. return c;
  422. }
  423. }
  424.  
  425. //コアとUIを繋いでいる。MVCモデルとかあまり学んでないけどCにあたるのかなあ?
  426.  
  427. class ButtonCellLightTogglingPropagatedListener implements LightTogglingPropagatedListener{
  428. JButton b = null;
  429. public ButtonCellLightTogglingPropagatedListener(JButton b1){
  430. b = b1;
  431. }
  432. // 引数は本当はもっとまともなものにしたい。
  433. public void lightTogglingPropagated(LightTogglingPropagatedEvent ev){
  434. if(ev.getStatus() == Status.BLANK){
  435. b.setBackground(java.awt.Color.GREEN);
  436. }else if(ev.getStatus() == Status.LIGHT){
  437.  
  438. b.setBackground(java.awt.Color.RED);
  439. }
  440. }
  441. }
  442.  
  443. class ButtonCellLightToggledListener implements LightToggledListener{
  444. JButton b = null;
  445. public ButtonCellLightToggledListener(JButton b1){
  446. b = b1;
  447. }
  448. // 引数は本当はもっとまともなものにしたい。
  449. public void lightToggled(LightToggledEvent ev){
  450. if(ev.getStatus() == Status.BLANK){
  451. b.setBackground(java.awt.Color.GREEN);
  452. }else if(ev.getStatus() == Status.LIGHT){
  453.  
  454. b.setBackground(java.awt.Color.BLUE);
  455. }
  456. }
  457. }
  458.  
  459.  
  460. class ButtonCellMaxLightsChangedListener implements MaxLightsChangedListener{
  461. JButton b = null;
  462. public ButtonCellMaxLightsChangedListener(JButton b1){
  463. b = b1;
  464. }
  465. // 引数は本当はもっとまともなものにしたい。
  466. public void maxLightsChanged(MaxLightsChangedEvent ev){
  467. b.setBackground(java.awt.Color.YELLOW);
  468. if(((Cell)ev.getSource()).getStatus() == Status.UNNUMBERED){
  469. return;
  470. }
  471. b.setText(Integer.toString(ev.getMaxLights()));
  472. }
  473. }
  474.  
  475.  
  476. // UIここまで
  477.  
  478. // あとは単なる起爆地点。
  479.  
  480. class Main{
  481. public static void main (String[] args) throws java.lang.Exception
  482. {
  483. Form1 f = new Form1();
  484.  
  485. f.setVisible(true);
  486. }
  487. }
Runtime error #stdin #stdout 0.1s 213888KB
stdin
1
1
4

1
4
-1

1
8
2

2
2
-1

2
8
-1

3
4
-1

3
5
0

6
4
1

6
5
-1

7
1
1

7
7
0

8
1
1

8
5
1

8
8
-1
stdout
Standard output is empty