Merge branch 'main' into DO-35-리플레이씬에서-기보-데이터로-돌-놓고-없애기
# Conflicts: # Assets/Resources/Prefabs/Panels/Main Panel.prefab # Assets/Script/UI/PanelController/ReplayPanelItemsController.cs 메인브랜치의 MainPanel로 통합 show().base 삭제로 해결
This commit is contained in:
commit
bd6a1cf6be
@ -214,102 +214,6 @@ MonoBehaviour:
|
|||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
panelManagerPrefab: {fileID: 3475740041361426276, guid: 085ca07ca90c92545b2594bd13412701, type: 3}
|
panelManagerPrefab: {fileID: 3475740041361426276, guid: 085ca07ca90c92545b2594bd13412701, type: 3}
|
||||||
audioManagerPrefab: {fileID: 2946408323859178723, guid: e829818dce39a5d4383e061111bed871, type: 3}
|
audioManagerPrefab: {fileID: 2946408323859178723, guid: e829818dce39a5d4383e061111bed871, type: 3}
|
||||||
--- !u!82 &271965292
|
|
||||||
AudioSource:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 271965288}
|
|
||||||
m_Enabled: 1
|
|
||||||
serializedVersion: 4
|
|
||||||
OutputAudioMixerGroup: {fileID: 0}
|
|
||||||
m_audioClip: {fileID: 0}
|
|
||||||
m_PlayOnAwake: 1
|
|
||||||
m_Volume: 1
|
|
||||||
m_Pitch: 1
|
|
||||||
Loop: 0
|
|
||||||
Mute: 0
|
|
||||||
Spatialize: 0
|
|
||||||
SpatializePostEffects: 0
|
|
||||||
Priority: 128
|
|
||||||
DopplerLevel: 1
|
|
||||||
MinDistance: 1
|
|
||||||
MaxDistance: 500
|
|
||||||
Pan2D: 0
|
|
||||||
rolloffMode: 0
|
|
||||||
BypassEffects: 0
|
|
||||||
BypassListenerEffects: 0
|
|
||||||
BypassReverbZones: 0
|
|
||||||
rolloffCustomCurve:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 1
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 1
|
|
||||||
value: 0
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 4
|
|
||||||
panLevelCustomCurve:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 0
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 4
|
|
||||||
spreadCustomCurve:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 0
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 4
|
|
||||||
reverbZoneMixCustomCurve:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 1
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 4
|
|
||||||
--- !u!1 &333752980
|
--- !u!1 &333752980
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -772,7 +676,7 @@ Canvas:
|
|||||||
m_OverridePixelPerfect: 0
|
m_OverridePixelPerfect: 0
|
||||||
m_SortingBucketNormalizedSize: 0
|
m_SortingBucketNormalizedSize: 0
|
||||||
m_VertexColorAlwaysGammaSpace: 0
|
m_VertexColorAlwaysGammaSpace: 0
|
||||||
m_AdditionalShaderChannelsFlag: 0
|
m_AdditionalShaderChannelsFlag: 25
|
||||||
m_UpdateRectTransformForStandalone: 0
|
m_UpdateRectTransformForStandalone: 0
|
||||||
m_SortingLayerID: 0
|
m_SortingLayerID: 0
|
||||||
m_SortingOrder: 0
|
m_SortingOrder: 0
|
||||||
@ -788,7 +692,8 @@ RectTransform:
|
|||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children:
|
||||||
|
- {fileID: 1545261106}
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
|
@ -38,4 +38,9 @@ public class MainPanelButtonController : MonoBehaviour
|
|||||||
{
|
{
|
||||||
GameManager.Instance.panelManager.OpenReplayPanel();
|
GameManager.Instance.panelManager.OpenReplayPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//public void OpenRankingPanelClick()
|
||||||
|
//{
|
||||||
|
//GameManager.Instance.panelManager.OnRankingPanelClick();
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
19688
Assets/KSH/GameCopy_AI.unity
Normal file
19688
Assets/KSH/GameCopy_AI.unity
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: e200b684d5479a643aa06e6361c430c9
|
guid: e61de5ff6b71b2e45b0878ccd8c8033a
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
@ -6020,6 +6020,50 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 9726acf6f82a3644ba31eda5ef496991, type: 3}
|
m_Script: {fileID: 11500000, guid: 9726acf6f82a3644ba31eda5ef496991, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
|
--- !u!1 &820078853
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 820078855}
|
||||||
|
- component: {fileID: 820078854}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: OmokAI
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!114 &820078854
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 820078853}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 576baa0fe98d40608bf48109ba5ed788, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
--- !u!4 &820078855
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 820078853}
|
||||||
|
serializedVersion: 2
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 540, y: 1760, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1001 &831992430
|
--- !u!1001 &831992430
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -8175,6 +8219,8 @@ GameObject:
|
|||||||
serializedVersion: 6
|
serializedVersion: 6
|
||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 1118625358}
|
- component: {fileID: 1118625358}
|
||||||
|
- component: {fileID: 1118625360}
|
||||||
|
- component: {fileID: 1118625359}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: GameManager
|
m_Name: GameManager
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@ -8197,6 +8243,116 @@ Transform:
|
|||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &1118625359
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1118625357}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 35a4c6d5d3a97b444b968e68ec8bb9f7, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
panelManagerPrefab: {fileID: 3475740041361426276, guid: 085ca07ca90c92545b2594bd13412701, type: 3}
|
||||||
|
audioManagerPrefab: {fileID: 2946408323859178723, guid: e829818dce39a5d4383e061111bed871, type: 3}
|
||||||
|
--- !u!82 &1118625360
|
||||||
|
AudioSource:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1118625357}
|
||||||
|
m_Enabled: 1
|
||||||
|
serializedVersion: 4
|
||||||
|
OutputAudioMixerGroup: {fileID: 0}
|
||||||
|
m_audioClip: {fileID: 0}
|
||||||
|
m_PlayOnAwake: 1
|
||||||
|
m_Volume: 1
|
||||||
|
m_Pitch: 1
|
||||||
|
Loop: 0
|
||||||
|
Mute: 0
|
||||||
|
Spatialize: 0
|
||||||
|
SpatializePostEffects: 0
|
||||||
|
Priority: 128
|
||||||
|
DopplerLevel: 1
|
||||||
|
MinDistance: 1
|
||||||
|
MaxDistance: 500
|
||||||
|
Pan2D: 0
|
||||||
|
rolloffMode: 0
|
||||||
|
BypassEffects: 0
|
||||||
|
BypassListenerEffects: 0
|
||||||
|
BypassReverbZones: 0
|
||||||
|
rolloffCustomCurve:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Curve:
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 0
|
||||||
|
value: 1
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0.33333334
|
||||||
|
outWeight: 0.33333334
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 1
|
||||||
|
value: 0
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0.33333334
|
||||||
|
outWeight: 0.33333334
|
||||||
|
m_PreInfinity: 2
|
||||||
|
m_PostInfinity: 2
|
||||||
|
m_RotationOrder: 4
|
||||||
|
panLevelCustomCurve:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Curve:
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 0
|
||||||
|
value: 0
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0.33333334
|
||||||
|
outWeight: 0.33333334
|
||||||
|
m_PreInfinity: 2
|
||||||
|
m_PostInfinity: 2
|
||||||
|
m_RotationOrder: 4
|
||||||
|
spreadCustomCurve:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Curve:
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 0
|
||||||
|
value: 0
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0.33333334
|
||||||
|
outWeight: 0.33333334
|
||||||
|
m_PreInfinity: 2
|
||||||
|
m_PostInfinity: 2
|
||||||
|
m_RotationOrder: 4
|
||||||
|
reverbZoneMixCustomCurve:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Curve:
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 0
|
||||||
|
value: 1
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0.33333334
|
||||||
|
outWeight: 0.33333334
|
||||||
|
m_PreInfinity: 2
|
||||||
|
m_PostInfinity: 2
|
||||||
|
m_RotationOrder: 4
|
||||||
--- !u!1001 &1121996003
|
--- !u!1001 &1121996003
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -17421,7 +17577,7 @@ PrefabInstance:
|
|||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 7155909258766834886, guid: b1a31da84076a534cae7cb20a7913a93, type: 3}
|
- target: {fileID: 7155909258766834886, guid: b1a31da84076a534cae7cb20a7913a93, type: 3}
|
||||||
propertyPath: m_Name
|
propertyPath: m_Name
|
||||||
value: '[Canvas] Game UI'
|
value: Canvas
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents: []
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
@ -17438,3 +17594,4 @@ SceneRoots:
|
|||||||
- {fileID: 307507522}
|
- {fileID: 307507522}
|
||||||
- {fileID: 1632066875}
|
- {fileID: 1632066875}
|
||||||
- {fileID: 1118625358}
|
- {fileID: 1118625358}
|
||||||
|
- {fileID: 820078855}
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ab181dd2d256816418fb8c9451e5114a
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -12,8 +12,6 @@ GameObject:
|
|||||||
- component: {fileID: 2911450618660204948}
|
- component: {fileID: 2911450618660204948}
|
||||||
- component: {fileID: 2729261171078307673}
|
- component: {fileID: 2729261171078307673}
|
||||||
- component: {fileID: 4465141290128179683}
|
- component: {fileID: 4465141290128179683}
|
||||||
- component: {fileID: 2835505888941074797}
|
|
||||||
- component: {fileID: 5687316735128766768}
|
|
||||||
m_Layer: 5
|
m_Layer: 5
|
||||||
m_Name: Viewport
|
m_Name: Viewport
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@ -37,7 +35,7 @@ RectTransform:
|
|||||||
m_Father: {fileID: 1188344226235047902}
|
m_Father: {fileID: 1188344226235047902}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
m_AnchorMax: {x: 0, y: 0}
|
||||||
m_AnchoredPosition: {x: 0, y: 0}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 0, y: 0}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0, y: 1}
|
m_Pivot: {x: 0, y: 1}
|
||||||
@ -92,46 +90,6 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
m_ShowMaskGraphic: 1
|
m_ShowMaskGraphic: 1
|
||||||
--- !u!114 &2835505888941074797
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 1858212639388121281}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_HorizontalFit: 1
|
|
||||||
m_VerticalFit: 2
|
|
||||||
--- !u!114 &5687316735128766768
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 1858212639388121281}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Padding:
|
|
||||||
m_Left: 0
|
|
||||||
m_Right: 0
|
|
||||||
m_Top: 0
|
|
||||||
m_Bottom: 0
|
|
||||||
m_ChildAlignment: 0
|
|
||||||
m_Spacing: 5
|
|
||||||
m_ChildForceExpandWidth: 1
|
|
||||||
m_ChildForceExpandHeight: 1
|
|
||||||
m_ChildControlWidth: 0
|
|
||||||
m_ChildControlHeight: 0
|
|
||||||
m_ChildScaleWidth: 0
|
|
||||||
m_ChildScaleHeight: 0
|
|
||||||
m_ReverseArrangement: 0
|
|
||||||
--- !u!1 &2602607401298266001
|
--- !u!1 &2602607401298266001
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -167,9 +125,9 @@ RectTransform:
|
|||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 1}
|
m_AnchorMin: {x: 0, y: 1}
|
||||||
m_AnchorMax: {x: 0, y: 1}
|
m_AnchorMax: {x: 0, y: 1}
|
||||||
m_AnchoredPosition: {x: 40, y: -40}
|
m_AnchoredPosition: {x: 80, y: -80}
|
||||||
m_SizeDelta: {x: 36, y: 40}
|
m_SizeDelta: {x: 80, y: 80}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.40175802, y: 0.5}
|
||||||
--- !u!222 &6169341149558268219
|
--- !u!222 &6169341149558268219
|
||||||
CanvasRenderer:
|
CanvasRenderer:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -198,7 +156,7 @@ MonoBehaviour:
|
|||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_Sprite: {fileID: 21300000, guid: 427761ad91f2d9d4e85af2f6a2894218, type: 3}
|
m_Sprite: {fileID: 21300000, guid: 2f19224efc36c9b49978cafd03ede1bb, type: 3}
|
||||||
m_Type: 0
|
m_Type: 0
|
||||||
m_PreserveAspect: 0
|
m_PreserveAspect: 0
|
||||||
m_FillCenter: 1
|
m_FillCenter: 1
|
||||||
@ -252,7 +210,7 @@ MonoBehaviour:
|
|||||||
m_OnClick:
|
m_OnClick:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls:
|
m_Calls:
|
||||||
- m_Target: {fileID: 0}
|
- m_Target: {fileID: 1589736077307570888}
|
||||||
m_TargetAssemblyTypeName: LeaderBoardController, Assembly-CSharp
|
m_TargetAssemblyTypeName: LeaderBoardController, Assembly-CSharp
|
||||||
m_MethodName: OnBackButtonClicked
|
m_MethodName: OnBackButtonClicked
|
||||||
m_Mode: 1
|
m_Mode: 1
|
||||||
@ -301,8 +259,8 @@ RectTransform:
|
|||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||||
m_AnchoredPosition: {x: 0, y: -212}
|
m_AnchoredPosition: {x: 0, y: -112.84912}
|
||||||
m_SizeDelta: {x: 1080, y: 1496}
|
m_SizeDelta: {x: 1080, y: 1694.3018}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!222 &824343901473742242
|
--- !u!222 &824343901473742242
|
||||||
CanvasRenderer:
|
CanvasRenderer:
|
||||||
@ -325,7 +283,7 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 0.392}
|
m_Color: {r: 1, g: 1, b: 1, a: 0}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
m_Maskable: 1
|
m_Maskable: 1
|
||||||
@ -361,14 +319,14 @@ MonoBehaviour:
|
|||||||
m_Elasticity: 0.1
|
m_Elasticity: 0.1
|
||||||
m_Inertia: 1
|
m_Inertia: 1
|
||||||
m_DecelerationRate: 0.135
|
m_DecelerationRate: 0.135
|
||||||
m_ScrollSensitivity: 1
|
m_ScrollSensitivity: 100
|
||||||
m_Viewport: {fileID: 8740302936727227434}
|
m_Viewport: {fileID: 8740302936727227434}
|
||||||
m_HorizontalScrollbar: {fileID: 0}
|
m_HorizontalScrollbar: {fileID: 0}
|
||||||
m_VerticalScrollbar: {fileID: 3478506922544614059}
|
m_VerticalScrollbar: {fileID: 3478506922544614059}
|
||||||
m_HorizontalScrollbarVisibility: 2
|
m_HorizontalScrollbarVisibility: 2
|
||||||
m_VerticalScrollbarVisibility: 2
|
m_VerticalScrollbarVisibility: 2
|
||||||
m_HorizontalScrollbarSpacing: -3
|
m_HorizontalScrollbarSpacing: -3
|
||||||
m_VerticalScrollbarSpacing: -3
|
m_VerticalScrollbarSpacing: -15
|
||||||
m_OnValueChanged:
|
m_OnValueChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
@ -523,6 +481,7 @@ GameObject:
|
|||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 227489081374553986}
|
- component: {fileID: 227489081374553986}
|
||||||
- component: {fileID: 6416582684501908282}
|
- component: {fileID: 6416582684501908282}
|
||||||
|
- component: {fileID: 2816695216852066709}
|
||||||
m_Layer: 5
|
m_Layer: 5
|
||||||
m_Name: Content
|
m_Name: Content
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@ -544,10 +503,10 @@ RectTransform:
|
|||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 8740302936727227434}
|
m_Father: {fileID: 8740302936727227434}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 1}
|
||||||
m_AnchorMax: {x: 0, y: 0}
|
m_AnchorMax: {x: 0, y: 1}
|
||||||
m_AnchoredPosition: {x: 0, y: 0}
|
m_AnchoredPosition: {x: 0, y: 0.000034332275}
|
||||||
m_SizeDelta: {x: 1060, y: 1493.8}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0, y: 1}
|
m_Pivot: {x: 0, y: 1}
|
||||||
--- !u!114 &6416582684501908282
|
--- !u!114 &6416582684501908282
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
@ -562,7 +521,7 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
m_Padding:
|
m_Padding:
|
||||||
m_Left: 0
|
m_Left: 100
|
||||||
m_Right: 0
|
m_Right: 0
|
||||||
m_Top: 0
|
m_Top: 0
|
||||||
m_Bottom: 0
|
m_Bottom: 0
|
||||||
@ -570,11 +529,25 @@ MonoBehaviour:
|
|||||||
m_Spacing: 50
|
m_Spacing: 50
|
||||||
m_ChildForceExpandWidth: 1
|
m_ChildForceExpandWidth: 1
|
||||||
m_ChildForceExpandHeight: 1
|
m_ChildForceExpandHeight: 1
|
||||||
m_ChildControlWidth: 1
|
m_ChildControlWidth: 0
|
||||||
m_ChildControlHeight: 1
|
m_ChildControlHeight: 0
|
||||||
m_ChildScaleWidth: 0
|
m_ChildScaleWidth: 0
|
||||||
m_ChildScaleHeight: 0
|
m_ChildScaleHeight: 0
|
||||||
m_ReverseArrangement: 0
|
m_ReverseArrangement: 0
|
||||||
|
--- !u!114 &2816695216852066709
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 3568653418969612126}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_HorizontalFit: 1
|
||||||
|
m_VerticalFit: 2
|
||||||
--- !u!1 &4202334049855500581
|
--- !u!1 &4202334049855500581
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -633,14 +606,14 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 1, g: 0, b: 0, a: 1}
|
m_Color: {r: 1, g: 0.9607843, b: 0.8980392, a: 0.32156864}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
m_Maskable: 1
|
m_Maskable: 1
|
||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
|
m_Sprite: {fileID: 21300000, guid: c06da2c324d0fee43b8b1998cf9fcd09, type: 3}
|
||||||
m_Type: 1
|
m_Type: 1
|
||||||
m_PreserveAspect: 0
|
m_PreserveAspect: 0
|
||||||
m_FillCenter: 1
|
m_FillCenter: 1
|
||||||
@ -659,9 +632,9 @@ GameObject:
|
|||||||
serializedVersion: 6
|
serializedVersion: 6
|
||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 2084150948806744478}
|
- component: {fileID: 2084150948806744478}
|
||||||
- component: {fileID: 7465938882283913230}
|
|
||||||
- component: {fileID: 1080045383039686757}
|
|
||||||
- component: {fileID: 3478506922544614059}
|
- component: {fileID: 3478506922544614059}
|
||||||
|
- component: {fileID: 6301460630123320729}
|
||||||
|
- component: {fileID: 1849839432792571899}
|
||||||
m_Layer: 5
|
m_Layer: 5
|
||||||
m_Name: Scrollbar Vertical
|
m_Name: Scrollbar Vertical
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@ -687,46 +660,8 @@ RectTransform:
|
|||||||
m_AnchorMin: {x: 1, y: 0}
|
m_AnchorMin: {x: 1, y: 0}
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
m_AnchoredPosition: {x: 0, y: 0}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 20, y: -17}
|
m_SizeDelta: {x: 20, y: 0}
|
||||||
m_Pivot: {x: 1, y: 1}
|
m_Pivot: {x: 1, y: 1}
|
||||||
--- !u!222 &7465938882283913230
|
|
||||||
CanvasRenderer:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 5452094549188284008}
|
|
||||||
m_CullTransparentMesh: 1
|
|
||||||
--- !u!114 &1080045383039686757
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 5452094549188284008}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Material: {fileID: 0}
|
|
||||||
m_Color: {r: 1, g: 0, b: 0, a: 1}
|
|
||||||
m_RaycastTarget: 1
|
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
m_Maskable: 1
|
|
||||||
m_OnCullStateChanged:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls: []
|
|
||||||
m_Sprite: {fileID: 0}
|
|
||||||
m_Type: 1
|
|
||||||
m_PreserveAspect: 0
|
|
||||||
m_FillCenter: 1
|
|
||||||
m_FillMethod: 4
|
|
||||||
m_FillAmount: 1
|
|
||||||
m_FillClockwise: 1
|
|
||||||
m_FillOrigin: 0
|
|
||||||
m_UseSpriteMesh: 0
|
|
||||||
m_PixelsPerUnitMultiplier: 1
|
|
||||||
--- !u!114 &3478506922544614059
|
--- !u!114 &3478506922544614059
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -746,12 +681,12 @@ MonoBehaviour:
|
|||||||
m_SelectOnDown: {fileID: 0}
|
m_SelectOnDown: {fileID: 0}
|
||||||
m_SelectOnLeft: {fileID: 0}
|
m_SelectOnLeft: {fileID: 0}
|
||||||
m_SelectOnRight: {fileID: 0}
|
m_SelectOnRight: {fileID: 0}
|
||||||
m_Transition: 1
|
m_Transition: 0
|
||||||
m_Colors:
|
m_Colors:
|
||||||
m_NormalColor: {r: 1, g: 0.55039775, b: 0, a: 1}
|
m_NormalColor: {r: 1, g: 0.28627452, b: 0, a: 1}
|
||||||
m_HighlightedColor: {r: 1, g: 0, b: 0, a: 1}
|
m_HighlightedColor: {r: 1, g: 0, b: 0, a: 1}
|
||||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
m_PressedColor: {r: 0.93710685, g: 0.33299702, b: 0.33299702, a: 1}
|
||||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
m_SelectedColor: {r: 0.8409424, g: 0.9685534, b: 0.57564956, a: 1}
|
||||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||||
m_ColorMultiplier: 1
|
m_ColorMultiplier: 1
|
||||||
m_FadeDuration: 0.1
|
m_FadeDuration: 0.1
|
||||||
@ -776,6 +711,44 @@ MonoBehaviour:
|
|||||||
m_OnValueChanged:
|
m_OnValueChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
|
--- !u!222 &6301460630123320729
|
||||||
|
CanvasRenderer:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 5452094549188284008}
|
||||||
|
m_CullTransparentMesh: 1
|
||||||
|
--- !u!114 &1849839432792571899
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 5452094549188284008}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Material: {fileID: 0}
|
||||||
|
m_Color: {r: 1, g: 0, b: 0, a: 0}
|
||||||
|
m_RaycastTarget: 1
|
||||||
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_Maskable: 1
|
||||||
|
m_OnCullStateChanged:
|
||||||
|
m_PersistentCalls:
|
||||||
|
m_Calls: []
|
||||||
|
m_Sprite: {fileID: 0}
|
||||||
|
m_Type: 0
|
||||||
|
m_PreserveAspect: 0
|
||||||
|
m_FillCenter: 1
|
||||||
|
m_FillMethod: 4
|
||||||
|
m_FillAmount: 1
|
||||||
|
m_FillClockwise: 1
|
||||||
|
m_FillOrigin: 0
|
||||||
|
m_UseSpriteMesh: 0
|
||||||
|
m_PixelsPerUnitMultiplier: 1
|
||||||
--- !u!1 &6747908716986530392
|
--- !u!1 &6747908716986530392
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -810,7 +783,7 @@ RectTransform:
|
|||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
m_AnchoredPosition: {x: 0, y: 0}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: -20, y: -20}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!1 &7787380462476439032
|
--- !u!1 &7787380462476439032
|
||||||
GameObject:
|
GameObject:
|
||||||
@ -882,7 +855,7 @@ RectTransform:
|
|||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 1}
|
m_AnchorMin: {x: 0, y: 1}
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
m_AnchoredPosition: {x: 0, y: -300}
|
m_AnchoredPosition: {x: 0, y: -115}
|
||||||
m_SizeDelta: {x: 0, y: 50}
|
m_SizeDelta: {x: 0, y: 50}
|
||||||
m_Pivot: {x: 0.5, y: 1}
|
m_Pivot: {x: 0.5, y: 1}
|
||||||
--- !u!222 &5432856254510042803
|
--- !u!222 &5432856254510042803
|
||||||
@ -913,7 +886,7 @@ MonoBehaviour:
|
|||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_text: Ranking
|
m_text: "\uB7AD\uD0B9"
|
||||||
m_isRightToLeft: 0
|
m_isRightToLeft: 0
|
||||||
m_fontAsset: {fileID: 11400000, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
m_fontAsset: {fileID: 11400000, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
||||||
m_sharedMaterial: {fileID: -2477908578676791210, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
m_sharedMaterial: {fileID: -2477908578676791210, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
||||||
|
@ -13,7 +13,7 @@ GameObject:
|
|||||||
- component: {fileID: 3015309825845733259}
|
- component: {fileID: 3015309825845733259}
|
||||||
- component: {fileID: 202560210887412943}
|
- component: {fileID: 202560210887412943}
|
||||||
m_Layer: 5
|
m_Layer: 5
|
||||||
m_Name: Rank Button
|
m_Name: Leaderboard Button
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
@ -388,9 +388,9 @@ MonoBehaviour:
|
|||||||
m_OnClick:
|
m_OnClick:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls:
|
m_Calls:
|
||||||
- m_Target: {fileID: 0}
|
- m_Target: {fileID: 7488082087611091670}
|
||||||
m_TargetAssemblyTypeName: PanelManager, Assembly-CSharp
|
m_TargetAssemblyTypeName: MainPanelController, Assembly-CSharp
|
||||||
m_MethodName: OpenSettingsPanel
|
m_MethodName: OpenSettingButtonClick
|
||||||
m_Mode: 1
|
m_Mode: 1
|
||||||
m_Arguments:
|
m_Arguments:
|
||||||
m_ObjectArgument: {fileID: 0}
|
m_ObjectArgument: {fileID: 0}
|
||||||
@ -410,7 +410,6 @@ GameObject:
|
|||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 2720476515686469179}
|
- component: {fileID: 2720476515686469179}
|
||||||
- component: {fileID: 7796730417217941349}
|
- component: {fileID: 7796730417217941349}
|
||||||
- component: {fileID: 5873276942444222861}
|
|
||||||
m_Layer: 5
|
m_Layer: 5
|
||||||
m_Name: Buttons
|
m_Name: Buttons
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@ -468,18 +467,6 @@ MonoBehaviour:
|
|||||||
m_ChildScaleWidth: 0
|
m_ChildScaleWidth: 0
|
||||||
m_ChildScaleHeight: 0
|
m_ChildScaleHeight: 0
|
||||||
m_ReverseArrangement: 0
|
m_ReverseArrangement: 0
|
||||||
--- !u!114 &5873276942444222861
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 1637449823560643887}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 93bfed50167472f489a27f0518070ed5, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
--- !u!1 &2440131775796007731
|
--- !u!1 &2440131775796007731
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -869,9 +856,9 @@ MonoBehaviour:
|
|||||||
m_OnClick:
|
m_OnClick:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls:
|
m_Calls:
|
||||||
- m_Target: {fileID: 5873276942444222861}
|
- m_Target: {fileID: 7488082087611091670}
|
||||||
m_TargetAssemblyTypeName: MainPanelButtonController, Assembly-CSharp
|
m_TargetAssemblyTypeName: MainPanelController, Assembly-CSharp
|
||||||
m_MethodName: OnShopPanelClick
|
m_MethodName: OnShopButtonClick
|
||||||
m_Mode: 1
|
m_Mode: 1
|
||||||
m_Arguments:
|
m_Arguments:
|
||||||
m_ObjectArgument: {fileID: 0}
|
m_ObjectArgument: {fileID: 0}
|
||||||
@ -1199,7 +1186,7 @@ GameObject:
|
|||||||
- component: {fileID: 5553341337845712589}
|
- component: {fileID: 5553341337845712589}
|
||||||
- component: {fileID: 837160915965981132}
|
- component: {fileID: 837160915965981132}
|
||||||
m_Layer: 5
|
m_Layer: 5
|
||||||
m_Name: Game Record Button
|
m_Name: Replay Button
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
@ -1307,9 +1294,9 @@ MonoBehaviour:
|
|||||||
m_OnClick:
|
m_OnClick:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls:
|
m_Calls:
|
||||||
- m_Target: {fileID: 5873276942444222861}
|
- m_Target: {fileID: 7488082087611091670}
|
||||||
m_TargetAssemblyTypeName: MainPanelButtonController, Assembly-CSharp
|
m_TargetAssemblyTypeName: MainPanelController, Assembly-CSharp
|
||||||
m_MethodName: OpenReplayPanelClick
|
m_MethodName: OpenReplayButtonClick
|
||||||
m_Mode: 1
|
m_Mode: 1
|
||||||
m_Arguments:
|
m_Arguments:
|
||||||
m_ObjectArgument: {fileID: 0}
|
m_ObjectArgument: {fileID: 0}
|
||||||
@ -1470,7 +1457,7 @@ GameObject:
|
|||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
m_StaticEditorFlags: 0
|
m_StaticEditorFlags: 0
|
||||||
m_IsActive: 1
|
m_IsActive: 0
|
||||||
--- !u!224 &405965270916774547
|
--- !u!224 &405965270916774547
|
||||||
RectTransform:
|
RectTransform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -1714,7 +1701,7 @@ MonoBehaviour:
|
|||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_text: "\uBC15\uC77C\uD658"
|
m_text: "\uD638\uB7AD\uC774"
|
||||||
m_isRightToLeft: 0
|
m_isRightToLeft: 0
|
||||||
m_fontAsset: {fileID: 11400000, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
m_fontAsset: {fileID: 11400000, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
||||||
m_sharedMaterial: {fileID: -2477908578676791210, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
m_sharedMaterial: {fileID: -2477908578676791210, guid: 85a19688db53c77469fc4406b01045da, type: 2}
|
||||||
@ -1800,7 +1787,7 @@ GameObject:
|
|||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
m_StaticEditorFlags: 0
|
m_StaticEditorFlags: 0
|
||||||
m_IsActive: 0
|
m_IsActive: 1
|
||||||
--- !u!224 &8172929902404983356
|
--- !u!224 &8172929902404983356
|
||||||
RectTransform:
|
RectTransform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -1,590 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!1 &154459105952450598
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 4212628350298048884}
|
|
||||||
- component: {fileID: 7043576313081816255}
|
|
||||||
- component: {fileID: 1260880031756413447}
|
|
||||||
- component: {fileID: 4783908613280260710}
|
|
||||||
- component: {fileID: 6733810038267402749}
|
|
||||||
m_Layer: 5
|
|
||||||
m_Name: Ranking Panel
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!224 &4212628350298048884
|
|
||||||
RectTransform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 154459105952450598}
|
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children:
|
|
||||||
- {fileID: 3321716118030398287}
|
|
||||||
m_Father: {fileID: 0}
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
|
||||||
m_AnchoredPosition: {x: 0, y: 0}
|
|
||||||
m_SizeDelta: {x: 0, y: 0}
|
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
|
||||||
--- !u!222 &7043576313081816255
|
|
||||||
CanvasRenderer:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 154459105952450598}
|
|
||||||
m_CullTransparentMesh: 1
|
|
||||||
--- !u!114 &1260880031756413447
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 154459105952450598}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Material: {fileID: 0}
|
|
||||||
m_Color: {r: 0, g: 0, b: 0, a: 0.74509805}
|
|
||||||
m_RaycastTarget: 1
|
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
m_Maskable: 1
|
|
||||||
m_OnCullStateChanged:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls: []
|
|
||||||
m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
|
|
||||||
m_Type: 1
|
|
||||||
m_PreserveAspect: 0
|
|
||||||
m_FillCenter: 1
|
|
||||||
m_FillMethod: 4
|
|
||||||
m_FillAmount: 1
|
|
||||||
m_FillClockwise: 1
|
|
||||||
m_FillOrigin: 0
|
|
||||||
m_UseSpriteMesh: 0
|
|
||||||
m_PixelsPerUnitMultiplier: 1
|
|
||||||
--- !u!225 &4783908613280260710
|
|
||||||
CanvasGroup:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 154459105952450598}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_Alpha: 1
|
|
||||||
m_Interactable: 1
|
|
||||||
m_BlocksRaycasts: 1
|
|
||||||
m_IgnoreParentGroups: 0
|
|
||||||
--- !u!114 &6733810038267402749
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 154459105952450598}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 5a1ec5e0ab0df4a418f3c30f67d8a1f9, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
panelRectTransform: {fileID: 3321716118030398287}
|
|
||||||
scrollItemPrefab: {fileID: 7605012172595602668, guid: 7f59e317567e58f48bffc6339a8718de, type: 3}
|
|
||||||
content: {fileID: 8786040817862643070}
|
|
||||||
--- !u!1 &1197605782786364269
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 5027046689765894947}
|
|
||||||
- component: {fileID: 1347723697007709839}
|
|
||||||
- component: {fileID: 1107002753484909144}
|
|
||||||
- component: {fileID: 3225345236067575878}
|
|
||||||
m_Layer: 5
|
|
||||||
m_Name: Close Button
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!224 &5027046689765894947
|
|
||||||
RectTransform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 1197605782786364269}
|
|
||||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children: []
|
|
||||||
m_Father: {fileID: 3321716118030398287}
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
|
||||||
m_AnchoredPosition: {x: 0, y: 750}
|
|
||||||
m_SizeDelta: {x: 80, y: 80}
|
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
|
||||||
--- !u!222 &1347723697007709839
|
|
||||||
CanvasRenderer:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 1197605782786364269}
|
|
||||||
m_CullTransparentMesh: 1
|
|
||||||
--- !u!114 &1107002753484909144
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 1197605782786364269}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Material: {fileID: 0}
|
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
||||||
m_RaycastTarget: 1
|
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
m_Maskable: 1
|
|
||||||
m_OnCullStateChanged:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls: []
|
|
||||||
m_Sprite: {fileID: 21300000, guid: 18ae4aac85f6d444b9ffb2ac80f27c45, type: 3}
|
|
||||||
m_Type: 0
|
|
||||||
m_PreserveAspect: 0
|
|
||||||
m_FillCenter: 1
|
|
||||||
m_FillMethod: 4
|
|
||||||
m_FillAmount: 1
|
|
||||||
m_FillClockwise: 1
|
|
||||||
m_FillOrigin: 0
|
|
||||||
m_UseSpriteMesh: 0
|
|
||||||
m_PixelsPerUnitMultiplier: 1
|
|
||||||
--- !u!114 &3225345236067575878
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 1197605782786364269}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Navigation:
|
|
||||||
m_Mode: 3
|
|
||||||
m_WrapAround: 0
|
|
||||||
m_SelectOnUp: {fileID: 0}
|
|
||||||
m_SelectOnDown: {fileID: 0}
|
|
||||||
m_SelectOnLeft: {fileID: 0}
|
|
||||||
m_SelectOnRight: {fileID: 0}
|
|
||||||
m_Transition: 1
|
|
||||||
m_Colors:
|
|
||||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
|
||||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
|
||||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
|
||||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
|
||||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
|
||||||
m_ColorMultiplier: 1
|
|
||||||
m_FadeDuration: 0.1
|
|
||||||
m_SpriteState:
|
|
||||||
m_HighlightedSprite: {fileID: 0}
|
|
||||||
m_PressedSprite: {fileID: 0}
|
|
||||||
m_SelectedSprite: {fileID: 0}
|
|
||||||
m_DisabledSprite: {fileID: 0}
|
|
||||||
m_AnimationTriggers:
|
|
||||||
m_NormalTrigger: Normal
|
|
||||||
m_HighlightedTrigger: Highlighted
|
|
||||||
m_PressedTrigger: Pressed
|
|
||||||
m_SelectedTrigger: Selected
|
|
||||||
m_DisabledTrigger: Disabled
|
|
||||||
m_Interactable: 1
|
|
||||||
m_TargetGraphic: {fileID: 1107002753484909144}
|
|
||||||
m_OnClick:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls:
|
|
||||||
- m_Target: {fileID: 6733810038267402749}
|
|
||||||
m_TargetAssemblyTypeName: ScrollPanelController, Assembly-CSharp
|
|
||||||
m_MethodName: OnClickCloseButton
|
|
||||||
m_Mode: 1
|
|
||||||
m_Arguments:
|
|
||||||
m_ObjectArgument: {fileID: 0}
|
|
||||||
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
|
|
||||||
m_IntArgument: 0
|
|
||||||
m_FloatArgument: 0
|
|
||||||
m_StringArgument:
|
|
||||||
m_BoolArgument: 0
|
|
||||||
m_CallState: 2
|
|
||||||
--- !u!1 &2986058160753478837
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 724496705792770137}
|
|
||||||
- component: {fileID: 8648493451823812328}
|
|
||||||
- component: {fileID: 7189945641146564510}
|
|
||||||
- component: {fileID: 2471937349441775619}
|
|
||||||
m_Layer: 5
|
|
||||||
m_Name: Viewport
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!224 &724496705792770137
|
|
||||||
RectTransform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 2986058160753478837}
|
|
||||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children:
|
|
||||||
- {fileID: 1763863758802443458}
|
|
||||||
m_Father: {fileID: 6370669554926347559}
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
m_AnchorMin: {x: 0, y: 0.04}
|
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
|
||||||
m_AnchoredPosition: {x: 0, y: 0}
|
|
||||||
m_SizeDelta: {x: -17, y: 0}
|
|
||||||
m_Pivot: {x: 0, y: 1}
|
|
||||||
--- !u!222 &8648493451823812328
|
|
||||||
CanvasRenderer:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 2986058160753478837}
|
|
||||||
m_CullTransparentMesh: 1
|
|
||||||
--- !u!114 &7189945641146564510
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 2986058160753478837}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Material: {fileID: 0}
|
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
||||||
m_RaycastTarget: 1
|
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
m_Maskable: 1
|
|
||||||
m_OnCullStateChanged:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls: []
|
|
||||||
m_Sprite: {fileID: 10917, guid: 0000000000000000f000000000000000, type: 0}
|
|
||||||
m_Type: 1
|
|
||||||
m_PreserveAspect: 0
|
|
||||||
m_FillCenter: 1
|
|
||||||
m_FillMethod: 4
|
|
||||||
m_FillAmount: 1
|
|
||||||
m_FillClockwise: 1
|
|
||||||
m_FillOrigin: 0
|
|
||||||
m_UseSpriteMesh: 0
|
|
||||||
m_PixelsPerUnitMultiplier: 1
|
|
||||||
--- !u!114 &2471937349441775619
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 2986058160753478837}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 31a19414c41e5ae4aae2af33fee712f6, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_ShowMaskGraphic: 0
|
|
||||||
--- !u!1 &4040312265684137449
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 6370669554926347559}
|
|
||||||
- component: {fileID: 5974489158367526773}
|
|
||||||
- component: {fileID: 3405436097124740100}
|
|
||||||
- component: {fileID: 8479784636977362532}
|
|
||||||
m_Layer: 5
|
|
||||||
m_Name: Scroll View
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!224 &6370669554926347559
|
|
||||||
RectTransform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 4040312265684137449}
|
|
||||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children:
|
|
||||||
- {fileID: 724496705792770137}
|
|
||||||
m_Father: {fileID: 3321716118030398287}
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
|
||||||
m_AnchorMax: {x: 1, y: 0.95600003}
|
|
||||||
m_AnchoredPosition: {x: 0, y: 0}
|
|
||||||
m_SizeDelta: {x: 0, y: 0}
|
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
|
||||||
--- !u!222 &5974489158367526773
|
|
||||||
CanvasRenderer:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 4040312265684137449}
|
|
||||||
m_CullTransparentMesh: 1
|
|
||||||
--- !u!114 &3405436097124740100
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 4040312265684137449}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Material: {fileID: 0}
|
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 0}
|
|
||||||
m_RaycastTarget: 1
|
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
m_Maskable: 1
|
|
||||||
m_OnCullStateChanged:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls: []
|
|
||||||
m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
|
|
||||||
m_Type: 1
|
|
||||||
m_PreserveAspect: 0
|
|
||||||
m_FillCenter: 1
|
|
||||||
m_FillMethod: 4
|
|
||||||
m_FillAmount: 1
|
|
||||||
m_FillClockwise: 1
|
|
||||||
m_FillOrigin: 0
|
|
||||||
m_UseSpriteMesh: 0
|
|
||||||
m_PixelsPerUnitMultiplier: 1
|
|
||||||
--- !u!114 &8479784636977362532
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 4040312265684137449}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 1aa08ab6e0800fa44ae55d278d1423e3, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Content: {fileID: 1763863758802443458}
|
|
||||||
m_Horizontal: 0
|
|
||||||
m_Vertical: 1
|
|
||||||
m_MovementType: 1
|
|
||||||
m_Elasticity: 0.1
|
|
||||||
m_Inertia: 1
|
|
||||||
m_DecelerationRate: 0.135
|
|
||||||
m_ScrollSensitivity: 1
|
|
||||||
m_Viewport: {fileID: 724496705792770137}
|
|
||||||
m_HorizontalScrollbar: {fileID: 0}
|
|
||||||
m_VerticalScrollbar: {fileID: 0}
|
|
||||||
m_HorizontalScrollbarVisibility: 2
|
|
||||||
m_VerticalScrollbarVisibility: 2
|
|
||||||
m_HorizontalScrollbarSpacing: -3
|
|
||||||
m_VerticalScrollbarSpacing: -3
|
|
||||||
m_OnValueChanged:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls: []
|
|
||||||
--- !u!1 &4310918944742421438
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 3321716118030398287}
|
|
||||||
- component: {fileID: 7726104613918846892}
|
|
||||||
- component: {fileID: 6090514240258565626}
|
|
||||||
m_Layer: 5
|
|
||||||
m_Name: Panel
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!224 &3321716118030398287
|
|
||||||
RectTransform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 4310918944742421438}
|
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children:
|
|
||||||
- {fileID: 5027046689765894947}
|
|
||||||
- {fileID: 6370669554926347559}
|
|
||||||
m_Father: {fileID: 4212628350298048884}
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
|
||||||
m_AnchoredPosition: {x: 0, y: 0}
|
|
||||||
m_SizeDelta: {x: 800, y: 1500}
|
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
|
||||||
--- !u!222 &7726104613918846892
|
|
||||||
CanvasRenderer:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 4310918944742421438}
|
|
||||||
m_CullTransparentMesh: 1
|
|
||||||
--- !u!114 &6090514240258565626
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 4310918944742421438}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Material: {fileID: 0}
|
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
|
||||||
m_RaycastTarget: 1
|
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
m_Maskable: 1
|
|
||||||
m_OnCullStateChanged:
|
|
||||||
m_PersistentCalls:
|
|
||||||
m_Calls: []
|
|
||||||
m_Sprite: {fileID: 21300000, guid: e89f6694961e7574b98368e14934a8b1, type: 3}
|
|
||||||
m_Type: 1
|
|
||||||
m_PreserveAspect: 0
|
|
||||||
m_FillCenter: 1
|
|
||||||
m_FillMethod: 4
|
|
||||||
m_FillAmount: 1
|
|
||||||
m_FillClockwise: 1
|
|
||||||
m_FillOrigin: 0
|
|
||||||
m_UseSpriteMesh: 0
|
|
||||||
m_PixelsPerUnitMultiplier: 1
|
|
||||||
--- !u!1 &8786040817862643070
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 1763863758802443458}
|
|
||||||
- component: {fileID: 5526954107552917871}
|
|
||||||
- component: {fileID: 189414464021159721}
|
|
||||||
m_Layer: 5
|
|
||||||
m_Name: Content
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!224 &1763863758802443458
|
|
||||||
RectTransform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 8786040817862643070}
|
|
||||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children: []
|
|
||||||
m_Father: {fileID: 724496705792770137}
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
m_AnchorMin: {x: 0.5, y: 0}
|
|
||||||
m_AnchorMax: {x: 0.5, y: 1}
|
|
||||||
m_AnchoredPosition: {x: -392, y: -2.9951172}
|
|
||||||
m_SizeDelta: {x: 784, y: 0}
|
|
||||||
m_Pivot: {x: 0, y: 1}
|
|
||||||
--- !u!114 &5526954107552917871
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 8786040817862643070}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_Padding:
|
|
||||||
m_Left: 0
|
|
||||||
m_Right: 0
|
|
||||||
m_Top: 0
|
|
||||||
m_Bottom: 0
|
|
||||||
m_ChildAlignment: 4
|
|
||||||
m_Spacing: 30
|
|
||||||
m_ChildForceExpandWidth: 1
|
|
||||||
m_ChildForceExpandHeight: 1
|
|
||||||
m_ChildControlWidth: 0
|
|
||||||
m_ChildControlHeight: 0
|
|
||||||
m_ChildScaleWidth: 0
|
|
||||||
m_ChildScaleHeight: 0
|
|
||||||
m_ReverseArrangement: 0
|
|
||||||
--- !u!114 &189414464021159721
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 8786040817862643070}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
m_HorizontalFit: 0
|
|
||||||
m_VerticalFit: 2
|
|
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 77313bc18c8074542b1e424d35507042
|
|
||||||
PrefabImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -315,7 +315,7 @@ MonoBehaviour:
|
|||||||
m_OnClick:
|
m_OnClick:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls:
|
m_Calls:
|
||||||
- m_Target: {fileID: 0}
|
- m_Target: {fileID: 1799015040358630920}
|
||||||
m_TargetAssemblyTypeName: ScrollPanelController, Assembly-CSharp
|
m_TargetAssemblyTypeName: ScrollPanelController, Assembly-CSharp
|
||||||
m_MethodName: OnClickCloseButton
|
m_MethodName: OnClickCloseButton
|
||||||
m_Mode: 1
|
m_Mode: 1
|
||||||
|
@ -350,7 +350,7 @@ RectTransform:
|
|||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0}
|
m_AnchorMin: {x: 0.5, y: 0}
|
||||||
m_AnchorMax: {x: 0.5, y: 1}
|
m_AnchorMax: {x: 0.5, y: 1}
|
||||||
m_AnchoredPosition: {x: -392, y: -56.72364}
|
m_AnchoredPosition: {x: -392, y: -5.683716}
|
||||||
m_SizeDelta: {x: 784, y: 0}
|
m_SizeDelta: {x: 784, y: 0}
|
||||||
m_Pivot: {x: 0, y: 1}
|
m_Pivot: {x: 0, y: 1}
|
||||||
--- !u!114 &2389273839879143832
|
--- !u!114 &2389273839879143832
|
||||||
|
@ -1166,7 +1166,7 @@ RectTransform:
|
|||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 0, y: 0}
|
m_AnchorMax: {x: 0, y: 0}
|
||||||
m_AnchoredPosition: {x: 0, y: 0}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 1060, y: 170}
|
m_SizeDelta: {x: 900, y: 170}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!114 &8547166501184847619
|
--- !u!114 &8547166501184847619
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
@ -1185,7 +1185,7 @@ MonoBehaviour:
|
|||||||
m_Right: 0
|
m_Right: 0
|
||||||
m_Top: 30
|
m_Top: 30
|
||||||
m_Bottom: 35
|
m_Bottom: 35
|
||||||
m_ChildAlignment: 0
|
m_ChildAlignment: 3
|
||||||
m_Spacing: 0
|
m_Spacing: 0
|
||||||
m_ChildForceExpandWidth: 1
|
m_ChildForceExpandWidth: 1
|
||||||
m_ChildForceExpandHeight: 1
|
m_ChildForceExpandHeight: 1
|
||||||
|
@ -392,7 +392,6 @@ GameObject:
|
|||||||
serializedVersion: 6
|
serializedVersion: 6
|
||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 1017982171}
|
- component: {fileID: 1017982171}
|
||||||
- component: {fileID: 1017982173}
|
|
||||||
- component: {fileID: 1017982172}
|
- component: {fileID: 1017982172}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: GameManager
|
m_Name: GameManager
|
||||||
@ -430,102 +429,6 @@ MonoBehaviour:
|
|||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
panelManagerPrefab: {fileID: 3475740041361426276, guid: 085ca07ca90c92545b2594bd13412701, type: 3}
|
panelManagerPrefab: {fileID: 3475740041361426276, guid: 085ca07ca90c92545b2594bd13412701, type: 3}
|
||||||
audioManagerPrefab: {fileID: 2946408323859178723, guid: e829818dce39a5d4383e061111bed871, type: 3}
|
audioManagerPrefab: {fileID: 2946408323859178723, guid: e829818dce39a5d4383e061111bed871, type: 3}
|
||||||
--- !u!82 &1017982173
|
|
||||||
AudioSource:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 1017982169}
|
|
||||||
m_Enabled: 1
|
|
||||||
serializedVersion: 4
|
|
||||||
OutputAudioMixerGroup: {fileID: 0}
|
|
||||||
m_audioClip: {fileID: 0}
|
|
||||||
m_PlayOnAwake: 1
|
|
||||||
m_Volume: 1
|
|
||||||
m_Pitch: 1
|
|
||||||
Loop: 0
|
|
||||||
Mute: 0
|
|
||||||
Spatialize: 0
|
|
||||||
SpatializePostEffects: 0
|
|
||||||
Priority: 128
|
|
||||||
DopplerLevel: 1
|
|
||||||
MinDistance: 1
|
|
||||||
MaxDistance: 500
|
|
||||||
Pan2D: 0
|
|
||||||
rolloffMode: 0
|
|
||||||
BypassEffects: 0
|
|
||||||
BypassListenerEffects: 0
|
|
||||||
BypassReverbZones: 0
|
|
||||||
rolloffCustomCurve:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 1
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 1
|
|
||||||
value: 0
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 4
|
|
||||||
panLevelCustomCurve:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 0
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 4
|
|
||||||
spreadCustomCurve:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 0
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 4
|
|
||||||
reverbZoneMixCustomCurve:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 1
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 4
|
|
||||||
--- !u!1 &1472647225
|
--- !u!1 &1472647225
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -5198,7 +5198,6 @@ GameObject:
|
|||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 679766978}
|
- component: {fileID: 679766978}
|
||||||
- component: {fileID: 679766977}
|
- component: {fileID: 679766977}
|
||||||
- component: {fileID: 679766979}
|
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: GameManager
|
m_Name: GameManager
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@ -5235,102 +5234,6 @@ Transform:
|
|||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!82 &679766979
|
|
||||||
AudioSource:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 679766976}
|
|
||||||
m_Enabled: 1
|
|
||||||
serializedVersion: 4
|
|
||||||
OutputAudioMixerGroup: {fileID: 0}
|
|
||||||
m_audioClip: {fileID: 0}
|
|
||||||
m_PlayOnAwake: 1
|
|
||||||
m_Volume: 1
|
|
||||||
m_Pitch: 1
|
|
||||||
Loop: 0
|
|
||||||
Mute: 0
|
|
||||||
Spatialize: 0
|
|
||||||
SpatializePostEffects: 0
|
|
||||||
Priority: 128
|
|
||||||
DopplerLevel: 1
|
|
||||||
MinDistance: 1
|
|
||||||
MaxDistance: 500
|
|
||||||
Pan2D: 0
|
|
||||||
rolloffMode: 0
|
|
||||||
BypassEffects: 0
|
|
||||||
BypassListenerEffects: 0
|
|
||||||
BypassReverbZones: 0
|
|
||||||
rolloffCustomCurve:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 1
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 1
|
|
||||||
value: 0
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 4
|
|
||||||
panLevelCustomCurve:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 0
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 4
|
|
||||||
spreadCustomCurve:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 0
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 4
|
|
||||||
reverbZoneMixCustomCurve:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 1
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 4
|
|
||||||
--- !u!1001 &681290285
|
--- !u!1001 &681290285
|
||||||
PrefabInstance:
|
PrefabInstance:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
12
Assets/Script/AI/AIConstants.cs
Normal file
12
Assets/Script/AI/AIConstants.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// AI에서만 사용하는 상수 모음
|
||||||
|
public class AIConstants
|
||||||
|
{
|
||||||
|
// 방향 상수
|
||||||
|
public static readonly int[][] Directions = new int[][]
|
||||||
|
{
|
||||||
|
new int[] {1, 0}, // 수직
|
||||||
|
new int[] {0, 1}, // 수평
|
||||||
|
new int[] {1, 1}, // 대각선 ↘ ↖
|
||||||
|
new int[] {1, -1} // 대각선 ↙ ↗
|
||||||
|
};
|
||||||
|
}
|
3
Assets/Script/AI/AIConstants.cs.meta
Normal file
3
Assets/Script/AI/AIConstants.cs.meta
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: de0993e48b9548668a73768a38c11b6d
|
||||||
|
timeCreated: 1742362879
|
580
Assets/Script/AI/AIEvaluator.cs
Normal file
580
Assets/Script/AI/AIEvaluator.cs
Normal file
@ -0,0 +1,580 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public static class AIEvaluator
|
||||||
|
{
|
||||||
|
// 패턴 가중치 상수
|
||||||
|
public struct PatternScore
|
||||||
|
{
|
||||||
|
// AI 패턴 점수
|
||||||
|
public const float FIVE_IN_A_ROW = 100000f;
|
||||||
|
public const float OPEN_FOUR = 15000f;
|
||||||
|
public const float HALF_OPEN_FOUR = 5000f;
|
||||||
|
public const float CLOSED_FOUR = 500f;
|
||||||
|
public const float OPEN_THREE = 3000f;
|
||||||
|
public const float HALF_OPEN_THREE = 500f;
|
||||||
|
public const float CLOSED_THREE = 50f;
|
||||||
|
public const float OPEN_TWO = 100f;
|
||||||
|
public const float HALF_OPEN_TWO = 30f;
|
||||||
|
public const float CLOSED_TWO = 10f;
|
||||||
|
public const float OPEN_ONE = 10f;
|
||||||
|
public const float CLOSED_ONE = 1f;
|
||||||
|
|
||||||
|
// 복합 패턴 점수
|
||||||
|
public const float DOUBLE_THREE = 8000f;
|
||||||
|
public const float DOUBLE_FOUR = 12000f;
|
||||||
|
public const float FOUR_THREE = 10000f;
|
||||||
|
|
||||||
|
// 위치 가중치 기본값
|
||||||
|
public const float CENTER_WEIGHT = 1.2f;
|
||||||
|
public const float EDGE_WEIGHT = 0.8f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly int[][] Directions = AIConstants.Directions;
|
||||||
|
|
||||||
|
// 보드 전체 상태 평가
|
||||||
|
public static float EvaluateBoard(Enums.PlayerType[,] board, Enums.PlayerType aiPlayer)
|
||||||
|
{
|
||||||
|
float score = 0;
|
||||||
|
int size = board.GetLength(0);
|
||||||
|
|
||||||
|
// 복합 패턴 감지를 위한 위치 저장 리스트
|
||||||
|
List<(int row, int col, int[] dir)> aiOpen3Positions = new List<(int, int, int[])>();
|
||||||
|
List<(int row, int col, int[] dir)> playerOpen3Positions = new List<(int, int, int[])>();
|
||||||
|
List<(int row, int col, int[] dir)> ai4Positions = new List<(int, int, int[])>();
|
||||||
|
List<(int row, int col, int[] dir)> player4Positions = new List<(int, int, int[])>();
|
||||||
|
|
||||||
|
// 1. 기본 패턴 평가
|
||||||
|
score += EvaluateBoardPatterns(board, aiPlayer, size, aiOpen3Positions, playerOpen3Positions,
|
||||||
|
ai4Positions, player4Positions);
|
||||||
|
|
||||||
|
// 2. 복합 패턴 평가
|
||||||
|
score += EvaluateComplexPatterns(aiOpen3Positions, playerOpen3Positions, ai4Positions, player4Positions, aiPlayer);
|
||||||
|
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 기본 패턴 (돌의 연속, 열린 끝 등) 평가
|
||||||
|
private static float EvaluateBoardPatterns(
|
||||||
|
Enums.PlayerType[,] board,
|
||||||
|
Enums.PlayerType aiPlayer,
|
||||||
|
int size,
|
||||||
|
List<(int row, int col, int[] dir)> aiOpen3Positions,
|
||||||
|
List<(int row, int col, int[] dir)> playerOpen3Positions,
|
||||||
|
List<(int row, int col, int[] dir)> ai4Positions,
|
||||||
|
List<(int row, int col, int[] dir)> player4Positions)
|
||||||
|
{
|
||||||
|
float score = 0;
|
||||||
|
Enums.PlayerType opponentPlayer = (aiPlayer == Enums.PlayerType.PlayerA) ?
|
||||||
|
Enums.PlayerType.PlayerB : Enums.PlayerType.PlayerA;
|
||||||
|
|
||||||
|
for (int row = 0; row < size; row++)
|
||||||
|
{
|
||||||
|
for (int col = 0; col < size; col++)
|
||||||
|
{
|
||||||
|
if (board[row, col] == Enums.PlayerType.None) continue;
|
||||||
|
|
||||||
|
Enums.PlayerType currentPlayer = board[row, col];
|
||||||
|
int playerScore = (currentPlayer == aiPlayer) ? 1 : -1; // AI는 양수, 플레이어는 음수
|
||||||
|
|
||||||
|
// 위치 가중치 계산
|
||||||
|
float positionWeight = CalculatePositionWeight(row, col, size);
|
||||||
|
|
||||||
|
foreach (var dir in Directions)
|
||||||
|
{
|
||||||
|
var (count, openEnds) = MiniMaxAIController.CountStones(board, row, col, dir, currentPlayer);
|
||||||
|
|
||||||
|
// 기본 패턴 평가 및 점수 계산
|
||||||
|
float patternScore = EvaluatePattern(count, openEnds);
|
||||||
|
|
||||||
|
// 깨진 패턴 평가
|
||||||
|
var (isBroken, brokenCount, brokenOpenEnds) =
|
||||||
|
DetectBrokenPattern(board, row, col, dir, currentPlayer);
|
||||||
|
|
||||||
|
if (isBroken) // 깨진 패턴이 있을 시 비교 후 더 높은 점수 할당
|
||||||
|
{
|
||||||
|
float brokenScore = EvaluateBrokenPattern(brokenCount, brokenOpenEnds);
|
||||||
|
patternScore = Math.Max(patternScore, brokenScore);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 패턴 수집 (복합 패턴 감지용)
|
||||||
|
CollectPatterns(row, col, dir, count, openEnds, currentPlayer, aiPlayer,
|
||||||
|
aiOpen3Positions, playerOpen3Positions, ai4Positions, player4Positions);
|
||||||
|
|
||||||
|
// 위치 가중치 적용
|
||||||
|
patternScore *= positionWeight;
|
||||||
|
|
||||||
|
// 최종 점수 (플레이어는 음수)
|
||||||
|
score += playerScore * patternScore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 개별 패턴 평가 (돌 개수와 열린 끝 기준)
|
||||||
|
private static float EvaluatePattern(int count, int openEnds)
|
||||||
|
{
|
||||||
|
if (count >= 5)
|
||||||
|
{
|
||||||
|
return PatternScore.FIVE_IN_A_ROW;
|
||||||
|
}
|
||||||
|
else if (count == 4)
|
||||||
|
{
|
||||||
|
return (openEnds == 2) ? PatternScore.OPEN_FOUR :
|
||||||
|
(openEnds == 1) ? PatternScore.HALF_OPEN_FOUR :
|
||||||
|
PatternScore.CLOSED_FOUR;
|
||||||
|
}
|
||||||
|
else if (count == 3)
|
||||||
|
{
|
||||||
|
return (openEnds == 2) ? PatternScore.OPEN_THREE :
|
||||||
|
(openEnds == 1) ? PatternScore.HALF_OPEN_THREE :
|
||||||
|
PatternScore.CLOSED_THREE;
|
||||||
|
}
|
||||||
|
else if (count == 2)
|
||||||
|
{
|
||||||
|
return (openEnds == 2) ? PatternScore.OPEN_TWO :
|
||||||
|
(openEnds == 1) ? PatternScore.HALF_OPEN_TWO :
|
||||||
|
PatternScore.CLOSED_TWO;
|
||||||
|
}
|
||||||
|
else if (count == 1)
|
||||||
|
{
|
||||||
|
return (openEnds == 2) ? PatternScore.OPEN_ONE : PatternScore.CLOSED_ONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 복합 패턴 평가 (3-3, 4-4, 4-3 등)
|
||||||
|
private static float EvaluateComplexPatterns(
|
||||||
|
List<(int row, int col, int[] dir)> aiOpen3Positions,
|
||||||
|
List<(int row, int col, int[] dir)> playerOpen3Positions,
|
||||||
|
List<(int row, int col, int[] dir)> ai4Positions,
|
||||||
|
List<(int row, int col, int[] dir)> player4Positions,
|
||||||
|
Enums.PlayerType aiPlayer)
|
||||||
|
{
|
||||||
|
float score = 0;
|
||||||
|
|
||||||
|
// 삼삼(3-3) 감지
|
||||||
|
int aiThreeThree = DetectDoubleThree(aiOpen3Positions);
|
||||||
|
int playerThreeThree = DetectDoubleThree(playerOpen3Positions);
|
||||||
|
|
||||||
|
// 사사(4-4) 감지
|
||||||
|
int aiFourFour = DetectDoubleFour(ai4Positions);
|
||||||
|
int playerFourFour = DetectDoubleFour(player4Positions);
|
||||||
|
|
||||||
|
// 사삼(4-3) 감지
|
||||||
|
int aiFourThree = DetectFourThree(ai4Positions, aiOpen3Positions);
|
||||||
|
int playerFourThree = DetectFourThree(player4Positions, playerOpen3Positions);
|
||||||
|
|
||||||
|
// 복합 패턴 점수 합산
|
||||||
|
score += aiThreeThree * PatternScore.DOUBLE_THREE;
|
||||||
|
score -= playerThreeThree * PatternScore.DOUBLE_THREE;
|
||||||
|
|
||||||
|
score += aiFourFour * PatternScore.DOUBLE_FOUR;
|
||||||
|
score -= playerFourFour * PatternScore.DOUBLE_FOUR;
|
||||||
|
|
||||||
|
score += aiFourThree * PatternScore.FOUR_THREE;
|
||||||
|
score -= playerFourThree * PatternScore.FOUR_THREE;
|
||||||
|
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 위치 가중치 계산 함수
|
||||||
|
private static float CalculatePositionWeight(int row, int col, int size)
|
||||||
|
{
|
||||||
|
float boardCenterPos = (size - 1) / 2.0f;
|
||||||
|
|
||||||
|
// 현재 위치와 중앙과의 거리 계산 (0~1 사이 값)
|
||||||
|
float distance = Math.Max(Math.Abs(row - boardCenterPos), Math.Abs(col - boardCenterPos)) / boardCenterPos;
|
||||||
|
|
||||||
|
// 중앙(거리 0)은 1.2배, 가장자리(거리 1)는 0.8배
|
||||||
|
return PatternScore.CENTER_WEIGHT - ((PatternScore.CENTER_WEIGHT - PatternScore.EDGE_WEIGHT) * distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 방향이 평행한지 확인하는 함수
|
||||||
|
private static bool AreParallelDirections(int[] dir1, int[] dir2) // Vector로 변경
|
||||||
|
{
|
||||||
|
return (dir1[0] == dir2[0] && dir1[1] == dir2[1]) ||
|
||||||
|
(dir1[0] == -dir2[0] && dir1[1] == -dir2[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 패턴 수집 함수 (복합 패턴 감지용)
|
||||||
|
private static void CollectPatterns(
|
||||||
|
int row, int col, int[] dir, int count, int openEnds,
|
||||||
|
Enums.PlayerType currentPlayer, Enums.PlayerType aiPlayer,
|
||||||
|
List<(int row, int col, int[] dir)> aiOpen3Positions,
|
||||||
|
List<(int row, int col, int[] dir)> playerOpen3Positions,
|
||||||
|
List<(int row, int col, int[] dir)> ai4Positions,
|
||||||
|
List<(int row, int col, int[] dir)> player4Positions)
|
||||||
|
{
|
||||||
|
// 열린 3 패턴 수집
|
||||||
|
if (count == 3 && openEnds == 2)
|
||||||
|
{
|
||||||
|
if (currentPlayer == aiPlayer)
|
||||||
|
aiOpen3Positions.Add((row, col, dir));
|
||||||
|
else
|
||||||
|
playerOpen3Positions.Add((row, col, dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4 패턴 수집
|
||||||
|
if (count == 4 && openEnds >= 1)
|
||||||
|
{
|
||||||
|
if (currentPlayer == aiPlayer)
|
||||||
|
ai4Positions.Add((row, col, dir));
|
||||||
|
else
|
||||||
|
player4Positions.Add((row, col, dir));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Complex Pattern (3-3, 4-4, 4-3)
|
||||||
|
// 삼삼(3-3) 감지 함수
|
||||||
|
private static int DetectDoubleThree(List<(int row, int col, int[] dir)> openThreePositions)
|
||||||
|
{
|
||||||
|
int doubleThreeCount = 0;
|
||||||
|
var checkedPairs = new HashSet<(int, int)>();
|
||||||
|
|
||||||
|
for (int i = 0; i < openThreePositions.Count; i++)
|
||||||
|
{
|
||||||
|
var (row1, col1, dir1) = openThreePositions[i];
|
||||||
|
|
||||||
|
for (int j = i + 1; j < openThreePositions.Count; j++)
|
||||||
|
{
|
||||||
|
var (row2, col2, dir2) = openThreePositions[j];
|
||||||
|
|
||||||
|
// 같은 돌에서 다른 방향으로 두 개의 열린 3이 형성된 경우
|
||||||
|
if (row1 == row2 && col1 == col2 && !AreParallelDirections(dir1, dir2))
|
||||||
|
{
|
||||||
|
if (!checkedPairs.Contains((row1, col1)))
|
||||||
|
{
|
||||||
|
doubleThreeCount++;
|
||||||
|
checkedPairs.Add((row1, col1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return doubleThreeCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 사사(4-4) 감지 함수
|
||||||
|
private static int DetectDoubleFour(List<(int row, int col, int[] dir)> fourPositions)
|
||||||
|
{
|
||||||
|
int doubleFourCount = 0;
|
||||||
|
var checkedPairs = new HashSet<(int, int)>();
|
||||||
|
|
||||||
|
for (int i = 0; i < fourPositions.Count; i++)
|
||||||
|
{
|
||||||
|
var (row1, col1, dir1) = fourPositions[i];
|
||||||
|
|
||||||
|
for (int j = i + 1; j < fourPositions.Count; j++)
|
||||||
|
{
|
||||||
|
var (row2, col2, dir2) = fourPositions[j];
|
||||||
|
|
||||||
|
if (row1 == row2 && col1 == col2 && !AreParallelDirections(dir1, dir2))
|
||||||
|
{
|
||||||
|
if (!checkedPairs.Contains((row1, col1)))
|
||||||
|
{
|
||||||
|
doubleFourCount++;
|
||||||
|
checkedPairs.Add((row1, col1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return doubleFourCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 사삼(4-3) 감지 함수
|
||||||
|
private static int DetectFourThree(
|
||||||
|
List<(int row, int col, int[] dir)> fourPositions,
|
||||||
|
List<(int row, int col, int[] dir)> openThreePositions)
|
||||||
|
{
|
||||||
|
int fourThreeCount = 0;
|
||||||
|
var checkedPairs = new HashSet<(int, int)>();
|
||||||
|
|
||||||
|
foreach (var (row1, col1, _) in fourPositions)
|
||||||
|
{
|
||||||
|
foreach (var (row2, col2, _) in openThreePositions)
|
||||||
|
{
|
||||||
|
// 같은 돌에서 4와 열린 3이 동시에 형성된 경우
|
||||||
|
if (row1 == row2 && col1 == col2)
|
||||||
|
{
|
||||||
|
if (!checkedPairs.Contains((row1, col1)))
|
||||||
|
{
|
||||||
|
fourThreeCount++;
|
||||||
|
checkedPairs.Add((row1, col1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fourThreeCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Evaluate Move Position
|
||||||
|
// 이동 평가 함수
|
||||||
|
public static float EvaluateMove(Enums.PlayerType[,] board, int row, int col, Enums.PlayerType AIPlayer)
|
||||||
|
{
|
||||||
|
float score = 0;
|
||||||
|
Enums.PlayerType opponentPlayer = (AIPlayer == Enums.PlayerType.PlayerA) ?
|
||||||
|
Enums.PlayerType.PlayerB : Enums.PlayerType.PlayerA;
|
||||||
|
|
||||||
|
// 복합 패턴 감지를 위한 위치 저장 리스트
|
||||||
|
List<(int[] dir, int count, int openEnds)> aiPatterns = new List<(int[], int, int)>();
|
||||||
|
List<(int[] dir, int count, int openEnds)> opponentPatterns = new List<(int[], int, int)>();
|
||||||
|
|
||||||
|
// AI 관점에서 평가
|
||||||
|
board[row, col] = AIPlayer;
|
||||||
|
|
||||||
|
foreach (var dir in Directions)
|
||||||
|
{
|
||||||
|
// 평가를 위한 가상 보드이기에 캐시 데이터에 저장X
|
||||||
|
var (count, openEnds) = MiniMaxAIController.CountStones(board, row, col, dir, AIPlayer, false);
|
||||||
|
aiPatterns.Add((dir, count, openEnds));
|
||||||
|
|
||||||
|
if (count >= 4)
|
||||||
|
{
|
||||||
|
score += PatternScore.FIVE_IN_A_ROW / 10;
|
||||||
|
}
|
||||||
|
else if (count == 3)
|
||||||
|
{
|
||||||
|
score += (openEnds == 2) ? PatternScore.OPEN_THREE / 3 :
|
||||||
|
(openEnds == 1) ? PatternScore.HALF_OPEN_THREE / 5 :
|
||||||
|
PatternScore.CLOSED_THREE / 5;
|
||||||
|
}
|
||||||
|
else if (count == 2)
|
||||||
|
{
|
||||||
|
score += (openEnds == 2) ? PatternScore.OPEN_TWO / 2 :
|
||||||
|
(openEnds == 1) ? PatternScore.HALF_OPEN_TWO / 3 :
|
||||||
|
PatternScore.CLOSED_TWO / 5;
|
||||||
|
}
|
||||||
|
else if (count == 1)
|
||||||
|
{
|
||||||
|
score += (openEnds == 2) ? PatternScore.OPEN_ONE :
|
||||||
|
PatternScore.CLOSED_ONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 깨진 패턴 평가
|
||||||
|
var (isBroken, brokenCount, brokenOpenEnds) = DetectBrokenPattern(board, row, col, dir, AIPlayer);
|
||||||
|
|
||||||
|
if (isBroken)
|
||||||
|
{
|
||||||
|
float brokenScore = EvaluateBrokenPattern(brokenCount, brokenOpenEnds);
|
||||||
|
score = Math.Max(score, brokenScore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AI 복합 패턴 점수 계산 (새로 추가)
|
||||||
|
score += EvaluateComplexMovePatterns(aiPatterns, true);
|
||||||
|
|
||||||
|
// 상대 관점에서 평가 (방어 가치)
|
||||||
|
board[row, col] = opponentPlayer;
|
||||||
|
|
||||||
|
foreach (var dir in Directions)
|
||||||
|
{
|
||||||
|
var (count, openEnds) = MiniMaxAIController.CountStones(board, row, col, dir, opponentPlayer, false);
|
||||||
|
opponentPatterns.Add((dir, count, openEnds));
|
||||||
|
|
||||||
|
// 상대 패턴 차단에 대한 가치 (약간 낮은 가중치)
|
||||||
|
if (count >= 4)
|
||||||
|
{
|
||||||
|
score += PatternScore.FIVE_IN_A_ROW / 12.5f;
|
||||||
|
}
|
||||||
|
else if (count == 3)
|
||||||
|
{
|
||||||
|
score += (openEnds == 2) ? PatternScore.OPEN_THREE / 3.75f :
|
||||||
|
(openEnds == 1) ? PatternScore.HALF_OPEN_THREE / 6.25f :
|
||||||
|
PatternScore.CLOSED_THREE / 6.25f;
|
||||||
|
}
|
||||||
|
else if (count == 2)
|
||||||
|
{
|
||||||
|
score += (openEnds == 2) ? PatternScore.OPEN_TWO / 2.5f :
|
||||||
|
(openEnds == 1) ? PatternScore.HALF_OPEN_TWO / 3.75f :
|
||||||
|
PatternScore.CLOSED_TWO / 5f;
|
||||||
|
}
|
||||||
|
else if (count == 1)
|
||||||
|
{
|
||||||
|
score += (openEnds == 2) ? PatternScore.OPEN_ONE / 1.25f :
|
||||||
|
PatternScore.CLOSED_ONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
score += EvaluateComplexMovePatterns(opponentPatterns, false);
|
||||||
|
|
||||||
|
// 원래 상태로 복원
|
||||||
|
board[row, col] = Enums.PlayerType.None;
|
||||||
|
|
||||||
|
// 중앙에 가까울수록 추가 점수
|
||||||
|
int size = board.GetLength(0);
|
||||||
|
float centerDistance = Math.Max(
|
||||||
|
Math.Abs(row - (size - 1) / 2.0f),
|
||||||
|
Math.Abs(col - (size - 1) / 2.0f)
|
||||||
|
);
|
||||||
|
float centerBonus = 1.0f - (centerDistance / ((size - 1) / 2.0f)) * 0.3f; // 30% 가중치
|
||||||
|
|
||||||
|
return score * centerBonus;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 복합 패턴 평가를 위한 새로운 함수
|
||||||
|
private static float EvaluateComplexMovePatterns(List<(int[] dir, int count, int openEnds)> patterns, bool isAI)
|
||||||
|
{
|
||||||
|
float score = 0;
|
||||||
|
|
||||||
|
// 열린 3 패턴 및 4 패턴 찾기
|
||||||
|
var openThrees = patterns.Where(p => p.count == 3 && p.openEnds == 2).ToList();
|
||||||
|
var fours = patterns.Where(p => p.count == 4 && p.openEnds >= 1).ToList();
|
||||||
|
|
||||||
|
// 3-3 패턴 감지
|
||||||
|
if (openThrees.Count >= 2)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < openThrees.Count; i++)
|
||||||
|
{
|
||||||
|
for (int j = i + 1; j < openThrees.Count; j++)
|
||||||
|
{
|
||||||
|
if (!AreParallelDirections(openThrees[i].dir, openThrees[j].dir))
|
||||||
|
{
|
||||||
|
float threeThreeScore = PatternScore.DOUBLE_THREE / 4; // 복합 패턴 가중치
|
||||||
|
score += isAI ? threeThreeScore : threeThreeScore;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4-4 패턴 감지
|
||||||
|
if (fours.Count >= 2)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < fours.Count; i++)
|
||||||
|
{
|
||||||
|
for (int j = i + 1; j < fours.Count; j++)
|
||||||
|
{
|
||||||
|
if (!AreParallelDirections(fours[i].dir, fours[j].dir))
|
||||||
|
{
|
||||||
|
float fourFourScore = PatternScore.DOUBLE_FOUR / 4;
|
||||||
|
score += isAI ? fourFourScore : fourFourScore;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4-3 패턴 감지
|
||||||
|
if (fours.Count > 0 && openThrees.Count > 0)
|
||||||
|
{
|
||||||
|
float fourThreeScore = PatternScore.FOUR_THREE / 4;
|
||||||
|
score += isAI ? fourThreeScore : fourThreeScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 깨진 패턴 (3-빈칸-1) 감지
|
||||||
|
private static (bool isDetected, int count, int openEnds) DetectBrokenPattern(
|
||||||
|
Enums.PlayerType[,] board, int row, int col, int[] dir, Enums.PlayerType player)
|
||||||
|
{
|
||||||
|
int size = board.GetLength(0);
|
||||||
|
int totalStones = 1; // 현재 위치의 돌 포함
|
||||||
|
int gapCount = 0; // 빈칸 개수
|
||||||
|
int openEnds = 0; // 열린 끝 개수
|
||||||
|
|
||||||
|
// 정방향 탐색
|
||||||
|
int r = row, c = col;
|
||||||
|
for (int i = 1; i <= 5; i++)
|
||||||
|
{
|
||||||
|
r += dir[0];
|
||||||
|
c += dir[1];
|
||||||
|
|
||||||
|
if (r < 0 || r >= size || c < 0 || c >= size)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (board[r, c] == player)
|
||||||
|
{
|
||||||
|
totalStones++;
|
||||||
|
}
|
||||||
|
else if (board[r, c] == Enums.PlayerType.None)
|
||||||
|
{
|
||||||
|
if (gapCount < 1) // 최대 1개 빈칸만 허용
|
||||||
|
{
|
||||||
|
gapCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
openEnds++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // 상대방 돌
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 역방향 탐색
|
||||||
|
r = row; c = col;
|
||||||
|
for (int i = 1; i <= 5; i++)
|
||||||
|
{
|
||||||
|
r -= dir[0];
|
||||||
|
c -= dir[1];
|
||||||
|
|
||||||
|
if (r < 0 || r >= size || c < 0 || c >= size)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (board[r, c] == player)
|
||||||
|
{
|
||||||
|
totalStones++;
|
||||||
|
}
|
||||||
|
else if (board[r, c] == Enums.PlayerType.None)
|
||||||
|
{
|
||||||
|
if (gapCount < 1)
|
||||||
|
{
|
||||||
|
gapCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
openEnds++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 깨진 패턴 감지: 총 돌 개수 ≥ 4 그리고 빈칸이 1개
|
||||||
|
bool isDetected = (totalStones >= 4 && gapCount == 1);
|
||||||
|
|
||||||
|
return (isDetected, totalStones, openEnds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 깨진 패턴 점수 계산 함수
|
||||||
|
private static float EvaluateBrokenPattern(int count, int openEnds)
|
||||||
|
{
|
||||||
|
if (count >= 5) // 5개 이상 돌이 있으면 승리
|
||||||
|
{
|
||||||
|
return PatternScore.FIVE_IN_A_ROW;
|
||||||
|
}
|
||||||
|
else if (count == 4) // 깨진 4
|
||||||
|
{
|
||||||
|
return (openEnds == 2) ? PatternScore.OPEN_FOUR * 0.8f :
|
||||||
|
(openEnds == 1) ? PatternScore.HALF_OPEN_FOUR * 0.8f :
|
||||||
|
PatternScore.CLOSED_FOUR * 0.7f;
|
||||||
|
}
|
||||||
|
else if (count == 3) // 깨진 3
|
||||||
|
{
|
||||||
|
return (openEnds == 2) ? PatternScore.OPEN_THREE * 0.7f :
|
||||||
|
(openEnds == 1) ? PatternScore.HALF_OPEN_THREE * 0.7f :
|
||||||
|
PatternScore.CLOSED_THREE * 0.6f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
3
Assets/Script/AI/AIEvaluator.cs.meta
Normal file
3
Assets/Script/AI/AIEvaluator.cs.meta
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 34f6533696ad41518da4bcc203309338
|
||||||
|
timeCreated: 1742357084
|
@ -5,34 +5,33 @@ using UnityEngine;
|
|||||||
|
|
||||||
public static class MiniMaxAIController
|
public static class MiniMaxAIController
|
||||||
{
|
{
|
||||||
// To-Do List
|
|
||||||
// 탐색 시간 개선: 캐싱(_stoneInfoCache), 좋은 수부터 탐색(Move Ordering)
|
|
||||||
// AI 난이도 개선
|
|
||||||
|
|
||||||
private const int SEARCH_DEPTH = 3; // 탐색 깊이 제한 (3 = 빠른 응답, 4 = 좀 더 강한 AI 그러나 느린)
|
private const int SEARCH_DEPTH = 3; // 탐색 깊이 제한 (3 = 빠른 응답, 4 = 좀 더 강한 AI 그러나 느린)
|
||||||
private const int WIN_COUNT = 5;
|
private const int WIN_COUNT = 5;
|
||||||
|
|
||||||
private static int[][] _directions = new int[][]
|
private static int[][] _directions = AIConstants.Directions;
|
||||||
{
|
|
||||||
new int[] {1, 0}, // 수직
|
|
||||||
new int[] {0, 1}, // 수평
|
|
||||||
new int[] {1, 1}, // 대각선 ↘ ↖
|
|
||||||
new int[] {1, -1} // 대각선 ↙ ↗
|
|
||||||
};
|
|
||||||
|
|
||||||
private static int _playerLevel = 1; // 급수 설정
|
private static int _playerLevel = 1; // 급수 설정
|
||||||
private static float _mistakeMove;
|
private static float _mistakeMove;
|
||||||
|
|
||||||
private static Enums.PlayerType _AIPlayerType = Enums.PlayerType.PlayerB;
|
private static Enums.PlayerType _AIPlayerType = Enums.PlayerType.PlayerB;
|
||||||
|
|
||||||
// 중복 계산을 방지하기 위한 캐싱 데이터. 위치(row, col) 와 방향(dirX, dirY) 중복 계산 방지
|
private static System.Random _random = new System.Random(); // 랜덤 실수용 Random 함수
|
||||||
private static Dictionary<(int, int, int, int), (int count, int openEnds)> _stoneInfoCache
|
|
||||||
= new Dictionary<(int, int, int, int), (int count, int openEnds)>();
|
// 중복 계산을 방지하기 위한 캐싱 데이터. 위치 기반 (그리드 기반 해시맵)
|
||||||
|
private static Dictionary<(int row, int col), Dictionary<(int dirX, int dirY), (int count, int openEnds)>>
|
||||||
|
_spatialStoneCache = new Dictionary<(int row, int col), Dictionary<(int dirX, int dirY), (int count, int openEnds)>>();
|
||||||
|
|
||||||
|
// AI Player Type 변경 (AI가 선수로 둘 수 있을지도 모르니..)
|
||||||
|
public static void SetAIPlayerType(Enums.PlayerType AIPlayerType)
|
||||||
|
{
|
||||||
|
_AIPlayerType = AIPlayerType;
|
||||||
|
}
|
||||||
|
|
||||||
// 급수 설정 -> 실수 넣을 때 계산
|
// 급수 설정 -> 실수 넣을 때 계산
|
||||||
public static void SetLevel(int level)
|
public static void SetLevel(int level)
|
||||||
{
|
{
|
||||||
_playerLevel = level;
|
_playerLevel = level;
|
||||||
|
// 레벨에 따른 실수율? 설정
|
||||||
_mistakeMove = GetMistakeProbability(_playerLevel);
|
_mistakeMove = GetMistakeProbability(_playerLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +70,7 @@ public static class MiniMaxAIController
|
|||||||
foreach (var (row, col, _) in validMoves)
|
foreach (var (row, col, _) in validMoves)
|
||||||
{
|
{
|
||||||
board[row, col] = _AIPlayerType;
|
board[row, col] = _AIPlayerType;
|
||||||
float score = DoMinimax(board, SEARCH_DEPTH, false, -1000, 1000, row, col);
|
float score = DoMinimax(board, SEARCH_DEPTH, false, -1000000, 1000000, row, col);
|
||||||
board[row, col] = Enums.PlayerType.None;
|
board[row, col] = Enums.PlayerType.None;
|
||||||
|
|
||||||
if (score > bestScore)
|
if (score > bestScore)
|
||||||
@ -88,7 +87,7 @@ public static class MiniMaxAIController
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 랜덤 실수
|
// 랜덤 실수
|
||||||
if (secondBestMove != null && UnityEngine.Random.value < _mistakeMove) // UnityEngine.Random.value == 0~1 사이 반환
|
if (secondBestMove != null && _random.NextDouble() < _mistakeMove)
|
||||||
{
|
{
|
||||||
Debug.Log("AI Mistake");
|
Debug.Log("AI Mistake");
|
||||||
return secondBestMove;
|
return secondBestMove;
|
||||||
@ -100,9 +99,9 @@ public static class MiniMaxAIController
|
|||||||
private static float DoMinimax(Enums.PlayerType[,] board, int depth, bool isMaximizing, float alpha, float beta,
|
private static float DoMinimax(Enums.PlayerType[,] board, int depth, bool isMaximizing, float alpha, float beta,
|
||||||
int recentRow, int recentCol)
|
int recentRow, int recentCol)
|
||||||
{
|
{
|
||||||
if (CheckGameWin(Enums.PlayerType.PlayerA, board, recentRow, recentCol)) return -100 + depth;
|
if (CheckGameWin(Enums.PlayerType.PlayerA, board, recentRow, recentCol, true)) return -100 + depth;
|
||||||
if (CheckGameWin(Enums.PlayerType.PlayerB, board, recentRow, recentCol)) return 100 - depth;
|
if (CheckGameWin(Enums.PlayerType.PlayerB, board, recentRow, recentCol, true)) return 100 - depth;
|
||||||
if (depth == 0) return EvaluateBoard(board);
|
if (depth == 0) return AIEvaluator.EvaluateBoard(board, _AIPlayerType);
|
||||||
|
|
||||||
float bestScore = isMaximizing ? float.MinValue : float.MaxValue;
|
float bestScore = isMaximizing ? float.MinValue : float.MaxValue;
|
||||||
List<(int row, int col, float score)> validMoves = GetValidMoves(board); // 현재 놓을 수 있는 자리 리스트
|
List<(int row, int col, float score)> validMoves = GetValidMoves(board); // 현재 놓을 수 있는 자리 리스트
|
||||||
@ -111,13 +110,11 @@ public static class MiniMaxAIController
|
|||||||
{
|
{
|
||||||
board[row, col] = isMaximizing ? Enums.PlayerType.PlayerB : Enums.PlayerType.PlayerA;
|
board[row, col] = isMaximizing ? Enums.PlayerType.PlayerB : Enums.PlayerType.PlayerA;
|
||||||
ClearCachePartial(row, col); // 부분 초기화
|
ClearCachePartial(row, col); // 부분 초기화
|
||||||
// ClearCache();
|
|
||||||
|
|
||||||
float minimaxScore = DoMinimax(board, depth - 1, !isMaximizing, alpha, beta, row, col);
|
float minimaxScore = DoMinimax(board, depth - 1, !isMaximizing, alpha, beta, row, col);
|
||||||
|
|
||||||
board[row, col] = Enums.PlayerType.None;
|
board[row, col] = Enums.PlayerType.None;
|
||||||
ClearCachePartial(row, col);
|
ClearCachePartial(row, col);
|
||||||
// ClearCache();
|
|
||||||
|
|
||||||
if (isMaximizing)
|
if (isMaximizing)
|
||||||
{
|
{
|
||||||
@ -147,14 +144,18 @@ public static class MiniMaxAIController
|
|||||||
{
|
{
|
||||||
if (board[row, col] == Enums.PlayerType.None && HasNearbyStones(board, row, col))
|
if (board[row, col] == Enums.PlayerType.None && HasNearbyStones(board, row, col))
|
||||||
{
|
{
|
||||||
float score = EvaluateBoard(board);
|
// 보드 전체가 아닌 해당 돌에 대해서만 Score 계산
|
||||||
|
float score = AIEvaluator.EvaluateMove(board, row, col, _AIPlayerType);
|
||||||
validMoves.Add((row, col, score));
|
validMoves.Add((row, col, score));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// score가 높은 순으로 정렬 -> 더 좋은 수 먼저 계산하도록 함
|
||||||
validMoves.Sort((a, b) => b.Item3.CompareTo(a.Item3));
|
validMoves.Sort((a, b) => b.Item3.CompareTo(a.Item3));
|
||||||
return validMoves;
|
|
||||||
|
// 시간 단축을 위해 상위 10-15개만 고려. 일단 15개
|
||||||
|
return validMoves.Take(15).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool HasNearbyStones(Enums.PlayerType[,] board, int row, int col, int distance = 3)
|
private static bool HasNearbyStones(Enums.PlayerType[,] board, int row, int col, int distance = 3)
|
||||||
@ -176,14 +177,16 @@ public static class MiniMaxAIController
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 특정 방향으로 같은 돌 개수와 열린 끝 개수를 계산하는 함수
|
// 특정 방향으로 같은 돌 개수와 열린 끝 개수를 계산하는 함수
|
||||||
private static (int count, int openEnds) CountStones(
|
public static (int count, int openEnds) CountStones(
|
||||||
Enums.PlayerType[,] board, int row, int col, int[] direction, Enums.PlayerType player)
|
Enums.PlayerType[,] board, int row, int col, int[] direction, Enums.PlayerType player, bool isSaveInCache = true)
|
||||||
{
|
{
|
||||||
int dirX = direction[0], dirY = direction[1];
|
int dirX = direction[0], dirY = direction[1];
|
||||||
var key = (row, col, dirX, dirY);
|
var posKey = (row, col);
|
||||||
|
var dirKey = (dirX, dirY);
|
||||||
|
|
||||||
// 캐시에 존재하면 바로 반환 (탐색 시간 감소)
|
// 캐시에 존재하면 바로 반환 (탐색 시간 감소)
|
||||||
if (_stoneInfoCache.TryGetValue(key, out var cachedResult))
|
if (_spatialStoneCache.TryGetValue(posKey, out var dirCache) &&
|
||||||
|
dirCache.TryGetValue(dirKey, out var cachedResult))
|
||||||
{
|
{
|
||||||
return cachedResult;
|
return cachedResult;
|
||||||
}
|
}
|
||||||
@ -222,53 +225,57 @@ public static class MiniMaxAIController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var resultValue = (count, openEnds);
|
var resultValue = (count, openEnds);
|
||||||
_stoneInfoCache[key] = resultValue; // 결과 저장
|
if(isSaveInCache) // 결과 저장
|
||||||
|
{
|
||||||
|
if (!_spatialStoneCache.TryGetValue(posKey, out dirCache))
|
||||||
|
{
|
||||||
|
dirCache = new Dictionary<(int, int), (int, int)>();
|
||||||
|
_spatialStoneCache[posKey] = dirCache;
|
||||||
|
}
|
||||||
|
dirCache[dirKey] = (count, openEnds);
|
||||||
|
}
|
||||||
|
|
||||||
return resultValue;
|
return resultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Cache Clear
|
||||||
|
|
||||||
// 캐시 초기화, 새로운 돌이 놓일 시 실행
|
// 캐시 초기화, 새로운 돌이 놓일 시 실행
|
||||||
private static void ClearCache()
|
private static void ClearCache()
|
||||||
{
|
{
|
||||||
_stoneInfoCache.Clear();
|
_spatialStoneCache.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 캐시 부분 초기화 (현재 변경된 위치 N에서 반경 5칸만 초기화)
|
// 캐시 부분 초기화 (현재 변경된 위치 N에서 반경 4칸만 초기화)
|
||||||
private static void ClearCachePartial(int centerRow, int centerCol, int radius = 5)
|
private static void ClearCachePartial(int centerRow, int centerCol, int radius = 4)
|
||||||
{
|
{
|
||||||
// 캐시가 비어있으면 아무 작업도 하지 않음
|
// 캐시가 비어있으면 아무 작업도 하지 않음
|
||||||
if (_stoneInfoCache.Count == 0) return;
|
if (_spatialStoneCache.Count == 0) return;
|
||||||
|
|
||||||
// 제거할 키 목록
|
|
||||||
List<(int, int, int, int)> keysToRemove = new List<(int, int, int, int)>();
|
|
||||||
|
|
||||||
// 모든 캐시 항목을 검사
|
|
||||||
foreach (var key in _stoneInfoCache.Keys)
|
|
||||||
{
|
|
||||||
var (row, col, _, _) = key;
|
|
||||||
|
|
||||||
// 거리 계산
|
|
||||||
int distance = Math.Max(Math.Abs(row - centerRow), Math.Abs(col - centerCol));
|
|
||||||
|
|
||||||
// 지정된 반경 내에 있는 캐시 항목을 삭제 목록에 추가
|
for (int r = centerRow - radius; r <= centerRow + radius; r++)
|
||||||
if (distance <= radius)
|
|
||||||
{
|
|
||||||
keysToRemove.Add(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 반경 내의 키 제거
|
|
||||||
foreach (var key in keysToRemove)
|
|
||||||
{
|
{
|
||||||
_stoneInfoCache.Remove(key);
|
for (int c = centerCol - radius; c <= centerCol + radius; c++)
|
||||||
|
{
|
||||||
|
// 반경 내 위치 확인
|
||||||
|
if (Math.Max(Math.Abs(r - centerRow), Math.Abs(c - centerCol)) <= radius)
|
||||||
|
{
|
||||||
|
// 해당 위치의 캐시 항목 제거
|
||||||
|
_spatialStoneCache.Remove((r, c));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
// 최근에 둔 돌 위치 기반으로 게임 승리를 판별하는 함수
|
// 최근에 둔 돌 위치 기반으로 게임 승리를 판별하는 함수
|
||||||
public static bool CheckGameWin(Enums.PlayerType player, Enums.PlayerType[,] board, int row, int col)
|
// MinimaxAIController 밖의 cs파일은 호출 시 맨 마지막을 false로 지정해야 합니다.
|
||||||
|
public static bool CheckGameWin(Enums.PlayerType player, Enums.PlayerType[,] board,
|
||||||
|
int row, int col, bool isSavedCache)
|
||||||
{
|
{
|
||||||
foreach (var dir in _directions)
|
foreach (var dir in _directions)
|
||||||
{
|
{
|
||||||
var (count, _) = CountStones(board, row, col, dir, player);
|
var (count, _) = CountStones(board, row, col, dir, player, isSavedCache);
|
||||||
|
|
||||||
// 자기 자신 포함하여 5개 이상일 시 true 반환
|
// 자기 자신 포함하여 5개 이상일 시 true 반환
|
||||||
if (count + 1 >= WIN_COUNT)
|
if (count + 1 >= WIN_COUNT)
|
||||||
@ -305,12 +312,91 @@ public static class MiniMaxAIController
|
|||||||
|
|
||||||
return fiveInARowMoves;
|
return fiveInARowMoves;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
#region Evaluate Score
|
||||||
|
|
||||||
|
// 특정 위치의 Score를 평가하는 새로운 함수
|
||||||
|
private static float EvaluateMove(Enums.PlayerType[,] board, int row, int col)
|
||||||
|
{
|
||||||
|
float score = 0;
|
||||||
|
board[row, col] = _AIPlayerType;
|
||||||
|
|
||||||
|
foreach (var dir in _directions)
|
||||||
|
{
|
||||||
|
// CountStones를 사용하나 캐시에 저장X, 가상 계산이기 때문..
|
||||||
|
var (count, openEnds) = CountStones(board, row, col, dir, _AIPlayerType, false);
|
||||||
|
|
||||||
|
if (count >= 4)
|
||||||
|
{
|
||||||
|
score += 10000;
|
||||||
|
}
|
||||||
|
else if (count == 3)
|
||||||
|
{
|
||||||
|
score += (openEnds == 2) ? 1000 : (openEnds == 1) ? 100 : 10;
|
||||||
|
}
|
||||||
|
else if (count == 2)
|
||||||
|
{
|
||||||
|
score += (openEnds == 2) ? 50 : (openEnds == 1) ? 10 : 5;
|
||||||
|
}
|
||||||
|
else if (count == 1)
|
||||||
|
{
|
||||||
|
score += (openEnds == 2) ? 10 : (openEnds == 1) ? 5 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 상대 돌로 바꿔서 평가
|
||||||
|
board[row, col] = Enums.PlayerType.PlayerB;
|
||||||
|
|
||||||
|
foreach (var dir in _directions)
|
||||||
|
{
|
||||||
|
// 캐시 저장X
|
||||||
|
var (count, openEnds) = CountStones(board, row, col, dir, Enums.PlayerType.PlayerB, false);
|
||||||
|
|
||||||
|
// 상대 패턴 차단에 대한 가치 (방어 점수)
|
||||||
|
if (count >= 4)
|
||||||
|
{
|
||||||
|
score += 8000;
|
||||||
|
}
|
||||||
|
else if (count == 3)
|
||||||
|
{
|
||||||
|
score += (openEnds == 2) ? 800 : (openEnds == 1) ? 80 : 8;
|
||||||
|
}
|
||||||
|
else if (count == 2)
|
||||||
|
{
|
||||||
|
score += (openEnds == 2) ? 40 : (openEnds == 1) ? 8 : 4;
|
||||||
|
}
|
||||||
|
else if (count == 1)
|
||||||
|
{
|
||||||
|
score += (openEnds == 2) ? 8 : (openEnds == 1) ? 4 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 원래 상태로 복원
|
||||||
|
board[row, col] = Enums.PlayerType.None;
|
||||||
|
|
||||||
|
// 중앙에 가까울수록 추가 점수
|
||||||
|
int size = board.GetLength(0);
|
||||||
|
float centerDistance = Math.Max(
|
||||||
|
Math.Abs(row - (size - 1) / 2.0f),
|
||||||
|
Math.Abs(col - (size - 1) / 2.0f)
|
||||||
|
);
|
||||||
|
float centerBonus = 1.0f - (centerDistance / ((size - 1) / 2.0f)) * 0.3f; // 30% 가중치
|
||||||
|
|
||||||
|
return score * centerBonus;
|
||||||
|
}
|
||||||
|
|
||||||
// 현재 보드 평가 함수
|
// 현재 보드 평가 함수
|
||||||
private static float EvaluateBoard(Enums.PlayerType[,] board)
|
private static float EvaluateBoard(Enums.PlayerType[,] board)
|
||||||
{
|
{
|
||||||
float score = 0;
|
float score = 0;
|
||||||
int size = board.GetLength(0);
|
int size = board.GetLength(0);
|
||||||
|
|
||||||
|
// 복합 패턴 감지를 위한 위치 저장 리스트
|
||||||
|
List<(int row, int col, int[] dir)> aiOpen3Positions = new List<(int, int, int[])>();
|
||||||
|
List<(int row, int col, int[] dir)> playerOpen3Positions = new List<(int, int, int[])>();
|
||||||
|
List<(int row, int col, int[] dir)> ai4Positions = new List<(int, int, int[])>();
|
||||||
|
List<(int row, int col, int[] dir)> player4Positions = new List<(int, int, int[])>();
|
||||||
|
|
||||||
|
|
||||||
for (int row = 0; row < size; row++)
|
for (int row = 0; row < size; row++)
|
||||||
{
|
{
|
||||||
@ -320,21 +406,191 @@ public static class MiniMaxAIController
|
|||||||
|
|
||||||
Enums.PlayerType player = board[row, col];
|
Enums.PlayerType player = board[row, col];
|
||||||
int playerScore = (player == _AIPlayerType) ? 1 : -1; // AI는 양수, 플레이어는 음수
|
int playerScore = (player == _AIPlayerType) ? 1 : -1; // AI는 양수, 플레이어는 음수
|
||||||
|
|
||||||
|
// 위치 가중치 계산. 중앙 중심으로 돌을 두도록 함
|
||||||
|
float positionWeight = CalculatePositionWeight(row, col, size);
|
||||||
|
|
||||||
foreach (var dir in _directions)
|
foreach (var dir in _directions)
|
||||||
{
|
{
|
||||||
var (count, openEnds) = CountStones(board, row, col, dir, player);
|
var (count, openEnds) = CountStones(board, row, col, dir, player);
|
||||||
|
|
||||||
// 점수 계산
|
// 점수 계산
|
||||||
if (count == 4)
|
float patternScore = 0;
|
||||||
score += playerScore * (openEnds == 2 ? 10000 : 1000);
|
|
||||||
|
if (count >= 5)
|
||||||
|
{
|
||||||
|
Debug.Log("over 5 counts. count amount: " + count);
|
||||||
|
patternScore = 100000;
|
||||||
|
}
|
||||||
|
else if (count == 4)
|
||||||
|
{
|
||||||
|
patternScore = (openEnds == 2) ? 15000 : (openEnds == 1) ? 5000 : 500;
|
||||||
|
|
||||||
|
// 4 패턴 위치 저장
|
||||||
|
if (openEnds >= 1)
|
||||||
|
{
|
||||||
|
if (player == _AIPlayerType)
|
||||||
|
ai4Positions.Add((row, col, dir));
|
||||||
|
else
|
||||||
|
player4Positions.Add((row, col, dir));
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (count == 3)
|
else if (count == 3)
|
||||||
score += playerScore * (openEnds == 2 ? 1000 : 100);
|
{
|
||||||
|
patternScore = (openEnds == 2) ? 3000 : (openEnds == 1) ? 500 : 50;
|
||||||
|
|
||||||
|
// 3 패턴 위치 저장
|
||||||
|
if (openEnds == 2)
|
||||||
|
{
|
||||||
|
if (player == _AIPlayerType)
|
||||||
|
aiOpen3Positions.Add((row, col, dir));
|
||||||
|
else
|
||||||
|
playerOpen3Positions.Add((row, col, dir));
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (count == 2)
|
else if (count == 2)
|
||||||
score += playerScore * (openEnds == 2 ? 100 : 10);
|
{
|
||||||
|
patternScore = (openEnds == 2) ? 100 : (openEnds == 1) ? 30 : 10;
|
||||||
|
}
|
||||||
|
else if (count == 1)
|
||||||
|
{
|
||||||
|
patternScore = (openEnds == 2) ? 10 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 위치 가중치 적용
|
||||||
|
patternScore *= positionWeight;
|
||||||
|
|
||||||
|
// 최종 점수 적용 (플레이어는 음수)
|
||||||
|
score += playerScore * patternScore;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. 복합 패턴 감지 및 점수 부여 (4,4 / 3,3 / 4,3)
|
||||||
|
int aiThreeThree = DetectDoubleThree(aiOpen3Positions);
|
||||||
|
int playerThreeThree = DetectDoubleThree(playerOpen3Positions);
|
||||||
|
|
||||||
|
int aiFourFour = DetectDoubleFour(ai4Positions);
|
||||||
|
int playerFourFour = DetectDoubleFour(player4Positions);
|
||||||
|
|
||||||
|
int aiFourThree = DetectFourThree(ai4Positions, aiOpen3Positions);
|
||||||
|
int playerFourThree = DetectFourThree(player4Positions, playerOpen3Positions);
|
||||||
|
|
||||||
|
// 복합 패턴 점수 추가
|
||||||
|
score += aiThreeThree * 8000;
|
||||||
|
score -= playerThreeThree * 8000;
|
||||||
|
|
||||||
|
score += aiFourFour * 12000;
|
||||||
|
score -= playerFourFour * 12000;
|
||||||
|
|
||||||
|
score += aiFourThree * 10000;
|
||||||
|
score -= playerFourThree * 10000;
|
||||||
|
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 위치 가중치 계산 함수
|
||||||
|
private static float CalculatePositionWeight(int row, int col, int size)
|
||||||
|
{
|
||||||
|
float boardCenterPos = (size - 1) / 2.0f;
|
||||||
|
|
||||||
|
// 현재 위치와 중앙과의 거리 계산 (0~1 사이 값)
|
||||||
|
float distance = Math.Max(Math.Abs(row - boardCenterPos), Math.Abs(col - boardCenterPos)) / boardCenterPos;
|
||||||
|
|
||||||
|
// 중앙(거리 0)은 1.2배, 가장자리(거리 1)는 0.8배
|
||||||
|
return 1.2f - (0.4f * distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 삼삼(3-3) 감지 함수
|
||||||
|
private static int DetectDoubleThree(List<(int row, int col, int[] dir)> openThreePositions)
|
||||||
|
{
|
||||||
|
int doubleThreeCount = 0;
|
||||||
|
var checkedPairs = new HashSet<(int, int)>();
|
||||||
|
|
||||||
|
for (int i = 0; i < openThreePositions.Count; i++)
|
||||||
|
{
|
||||||
|
var (row1, col1, dir1) = openThreePositions[i];
|
||||||
|
|
||||||
|
for (int j = i + 1; j < openThreePositions.Count; j++)
|
||||||
|
{
|
||||||
|
var (row2, col2, dir2) = openThreePositions[j];
|
||||||
|
|
||||||
|
// 같은 돌에서 다른 방향으로 두 개의 열린 3이 형성된 경우
|
||||||
|
if (row1 == row2 && col1 == col2 && !AreParallelDirections(dir1, dir2))
|
||||||
|
{
|
||||||
|
if (!checkedPairs.Contains((row1, col1)))
|
||||||
|
{
|
||||||
|
doubleThreeCount++;
|
||||||
|
checkedPairs.Add((row1, col1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return doubleThreeCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 방향이 평행한지 확인하는 함수
|
||||||
|
private static bool AreParallelDirections(int[] dir1, int[] dir2)
|
||||||
|
{
|
||||||
|
return (dir1[0] == dir2[0] && dir1[1] == dir2[1]) ||
|
||||||
|
(dir1[0] == -dir2[0] && dir1[1] == -dir2[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 사사(4-4) 감지 함수
|
||||||
|
private static int DetectDoubleFour(List<(int row, int col, int[] dir)> fourPositions)
|
||||||
|
{
|
||||||
|
int doubleFourCount = 0;
|
||||||
|
var checkedPairs = new HashSet<(int, int)>();
|
||||||
|
|
||||||
|
for (int i = 0; i < fourPositions.Count; i++)
|
||||||
|
{
|
||||||
|
var (row1, col1, dir1) = fourPositions[i];
|
||||||
|
|
||||||
|
for (int j = i + 1; j < fourPositions.Count; j++)
|
||||||
|
{
|
||||||
|
var (row2, col2, dir2) = fourPositions[j];
|
||||||
|
|
||||||
|
if (row1 == row2 && col1 == col2 && !AreParallelDirections(dir1, dir2))
|
||||||
|
{
|
||||||
|
if (!checkedPairs.Contains((row1, col1)))
|
||||||
|
{
|
||||||
|
doubleFourCount++;
|
||||||
|
checkedPairs.Add((row1, col1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return doubleFourCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 사삼(4-3) 감지 함수
|
||||||
|
private static int DetectFourThree(List<(int row, int col, int[] dir)> fourPositions,
|
||||||
|
List<(int row, int col, int[] dir)> openThreePositions)
|
||||||
|
{
|
||||||
|
int fourThreeCount = 0;
|
||||||
|
var checkedPairs = new HashSet<(int, int)>();
|
||||||
|
|
||||||
|
foreach (var (row1, col1, _) in fourPositions)
|
||||||
|
{
|
||||||
|
foreach (var (row2, col2, _) in openThreePositions)
|
||||||
|
{
|
||||||
|
// 같은 돌에서 4와 열린 3이 동시에 형성된 경우
|
||||||
|
if (row1 == row2 && col1 == col2)
|
||||||
|
{
|
||||||
|
if (!checkedPairs.Contains((row1, col1)))
|
||||||
|
{
|
||||||
|
fourThreeCount++;
|
||||||
|
checkedPairs.Add((row1, col1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fourThreeCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
26
Assets/Script/AI/OmokAI.cs
Normal file
26
Assets/Script/AI/OmokAI.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public class OmokAI : MonoBehaviour
|
||||||
|
{
|
||||||
|
public static OmokAI Instance;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
Instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void StartBestMoveSearch(Enums.PlayerType[,] board, Action<(int, int)?> callback)
|
||||||
|
{
|
||||||
|
(int row, int col)? bestMove = await Task.Run(() => MiniMaxAIController.GetBestMove(board));
|
||||||
|
callback?.Invoke(bestMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
// true: Win, false: Lose
|
||||||
|
public bool CheckGameWin(Enums.PlayerType player, Enums.PlayerType[,] board, int row, int col)
|
||||||
|
{
|
||||||
|
bool isWin = MiniMaxAIController.CheckGameWin(player, board, row, col, false);
|
||||||
|
return isWin;
|
||||||
|
}
|
||||||
|
}
|
3
Assets/Script/AI/OmokAI.cs.meta
Normal file
3
Assets/Script/AI/OmokAI.cs.meta
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 576baa0fe98d40608bf48109ba5ed788
|
||||||
|
timeCreated: 1742286909
|
@ -1,84 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using TMPro;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Serialization;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
|
|
||||||
public class TestGameManager : MonoBehaviour
|
|
||||||
{
|
|
||||||
[SerializeField] private TMP_InputField rowText;
|
|
||||||
[SerializeField] private TMP_InputField colText;
|
|
||||||
[SerializeField] private TMP_Text boardText;
|
|
||||||
|
|
||||||
private Enums.PlayerType[,] _board;
|
|
||||||
|
|
||||||
private void Start()
|
|
||||||
{
|
|
||||||
_board = new Enums.PlayerType[15, 15];
|
|
||||||
MiniMaxAIController.SetLevel(1); // 급수 설정 테스트
|
|
||||||
ResultBoard();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnClickGoButton()
|
|
||||||
{
|
|
||||||
int row = int.Parse(rowText.text);
|
|
||||||
int col = int.Parse(colText.text);
|
|
||||||
|
|
||||||
if (_board[row, col] != Enums.PlayerType.None)
|
|
||||||
{
|
|
||||||
Debug.Log("중복 위치");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_board[row, col] = Enums.PlayerType.PlayerA;
|
|
||||||
Debug.Log($"Player's row: {row} col: {col}");
|
|
||||||
|
|
||||||
// var isEnded = MiniMaxAIController.CheckGameWin(Enums.PlayerType.PlayerA, _board, row, col);
|
|
||||||
// Debug.Log("PlayerA is Win: " + isEnded);
|
|
||||||
|
|
||||||
// 인공지능 호출
|
|
||||||
var result = MiniMaxAIController.GetBestMove(_board);
|
|
||||||
|
|
||||||
if (result.HasValue)
|
|
||||||
{
|
|
||||||
Debug.Log($"AI's row: {result.Value.row} col: {result.Value.col}");
|
|
||||||
_board[result.Value.row, result.Value.col] = Enums.PlayerType.PlayerB;
|
|
||||||
|
|
||||||
// isEnded = MiniMaxAIController.CheckGameWin(Enums.PlayerType.PlayerB, _board, result.Value.row, result.Value.col);
|
|
||||||
// Debug.Log("PlayerB is Win: " + isEnded);
|
|
||||||
}
|
|
||||||
|
|
||||||
ResultBoard();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ResultBoard()
|
|
||||||
{
|
|
||||||
boardText.text = "";
|
|
||||||
|
|
||||||
// player 타입에 따라 입력받는 건 무조건 A로 해서 A, AI는 B로 나타내고 None은 _
|
|
||||||
for (int i = 0; i < 15; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < 15; j++)
|
|
||||||
{
|
|
||||||
if (_board[i, j] == Enums.PlayerType.PlayerA)
|
|
||||||
{
|
|
||||||
boardText.text += 'A';
|
|
||||||
}
|
|
||||||
else if (_board[i, j] == Enums.PlayerType.PlayerB)
|
|
||||||
{
|
|
||||||
boardText.text += 'B';
|
|
||||||
}
|
|
||||||
else if (_board[i, j] == Enums.PlayerType.None)
|
|
||||||
{
|
|
||||||
boardText.text += '_';
|
|
||||||
}
|
|
||||||
|
|
||||||
boardText.text += ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
boardText.text += '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: facc79abb6042e846bb0a2b099b58e9c
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,5 +1,6 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
[RequireComponent(typeof(AudioSource))]
|
||||||
public class AudioManager : MonoBehaviour
|
public class AudioManager : MonoBehaviour
|
||||||
{
|
{
|
||||||
[Header("Sound")]
|
[Header("Sound")]
|
||||||
@ -22,7 +23,7 @@ public class AudioManager : MonoBehaviour
|
|||||||
// 배경음악이 설정되면 재생
|
// 배경음악이 설정되면 재생
|
||||||
audioSource.clip = mainBgm; // 음악 클립 설정
|
audioSource.clip = mainBgm; // 음악 클립 설정
|
||||||
audioSource.loop = true; // 반복 재생
|
audioSource.loop = true; // 반복 재생
|
||||||
audioSource.volume = 0.4f; // 볼륨
|
audioSource.volume = 0.2f; // 볼륨
|
||||||
audioSource.Play(); // 음악 시작
|
audioSource.Play(); // 음악 시작
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,4 +4,7 @@
|
|||||||
public const string GameServerURL = "ws://localhost:3000";
|
public const string GameServerURL = "ws://localhost:3000";
|
||||||
public const int BoardSize = 15;
|
public const int BoardSize = 15;
|
||||||
public const int ReplayMaxRecordSize = 10;
|
public const int ReplayMaxRecordSize = 10;
|
||||||
|
public const int WIN_COUNT = 5;
|
||||||
|
//무승부 확인을 위한 최소 착수 수
|
||||||
|
public const int MinCountForDrawCheck = 150;
|
||||||
}
|
}
|
@ -12,10 +12,10 @@ public abstract class BasePlayerState
|
|||||||
|
|
||||||
public void ProcessMove(GameLogic gameLogic, Enums.PlayerType playerType, int row, int col)
|
public void ProcessMove(GameLogic gameLogic, Enums.PlayerType playerType, int row, int col)
|
||||||
{
|
{
|
||||||
|
|
||||||
gameLogic.fioTimer.PauseTimer();
|
gameLogic.fioTimer.PauseTimer();
|
||||||
|
|
||||||
gameLogic.SetNewBoardValue(playerType, row, col);
|
gameLogic.SetNewBoardValue(playerType, row, col);
|
||||||
|
gameLogic.CountStoneCounter();
|
||||||
|
|
||||||
if (gameLogic.CheckGameWin(playerType, row, col))
|
if (gameLogic.CheckGameWin(playerType, row, col))
|
||||||
{
|
{
|
||||||
@ -24,10 +24,23 @@ public abstract class BasePlayerState
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//TODO: 무승부 확인
|
if (gameLogic.TotalStoneCounter >= Constants.MinCountForDrawCheck)
|
||||||
HandleNextTurn(gameLogic);
|
{
|
||||||
|
if (gameLogic.CheckGameDraw())
|
||||||
|
{
|
||||||
|
GameManager.Instance.panelManager.OpenConfirmPanel($"Game Over: Draw",() =>{});
|
||||||
|
gameLogic.EndGame();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HandleNextTurn(gameLogic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HandleNextTurn(gameLogic);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +98,11 @@ public class AIState: BasePlayerState
|
|||||||
public override void OnEnter(GameLogic gameLogic)
|
public override void OnEnter(GameLogic gameLogic)
|
||||||
{
|
{
|
||||||
gameLogic.fioTimer.StartTimer();
|
gameLogic.fioTimer.StartTimer();
|
||||||
//TODO: AI이식
|
OmokAI.Instance.StartBestMoveSearch(gameLogic.GetBoard(), (bestMove) =>
|
||||||
|
{
|
||||||
|
if(bestMove.HasValue)
|
||||||
|
HandleMove(gameLogic, bestMove.Value.Item1, bestMove.Value.Item2);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnExit(GameLogic gameLogic)
|
public override void OnExit(GameLogic gameLogic)
|
||||||
@ -132,17 +149,23 @@ public class GameLogic : MonoBehaviour
|
|||||||
public StoneController stoneController;
|
public StoneController stoneController;
|
||||||
public Enums.PlayerType currentTurn;
|
public Enums.PlayerType currentTurn;
|
||||||
public Enums.GameType gameType;
|
public Enums.GameType gameType;
|
||||||
|
//총 착수된 돌 카운터
|
||||||
|
public int _totalStoneCounter;
|
||||||
|
public int TotalStoneCounter{get{return _totalStoneCounter;}}
|
||||||
|
|
||||||
public BasePlayerState firstPlayerState;
|
public BasePlayerState firstPlayerState;
|
||||||
public BasePlayerState secondPlayerState;
|
public BasePlayerState secondPlayerState;
|
||||||
private BasePlayerState _currentPlayerState;
|
private BasePlayerState _currentPlayerState;
|
||||||
|
//타이머
|
||||||
public FioTimer fioTimer;
|
public FioTimer fioTimer;
|
||||||
|
|
||||||
private const int WIN_COUNT = 5;
|
|
||||||
//선택된 좌표
|
//선택된 좌표
|
||||||
public int selectedRow;
|
public int selectedRow;
|
||||||
public int selectedCol;
|
public int selectedCol;
|
||||||
//마지막 배치된 좌표
|
//마지막 배치된 좌표
|
||||||
|
private int _lastRow;
|
||||||
|
private int _lastCol;
|
||||||
|
|
||||||
#region Renju Members
|
#region Renju Members
|
||||||
// 렌주룰 금수 검사기
|
// 렌주룰 금수 검사기
|
||||||
private RenjuForbiddenMoveDetector _forbiddenDetector;
|
private RenjuForbiddenMoveDetector _forbiddenDetector;
|
||||||
@ -151,9 +174,6 @@ public class GameLogic : MonoBehaviour
|
|||||||
private List<Vector2Int> _forbiddenMoves = new List<Vector2Int>();
|
private List<Vector2Int> _forbiddenMoves = new List<Vector2Int>();
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private int _lastRow;
|
|
||||||
private int _lastCol;
|
|
||||||
|
|
||||||
private static int[][] _directions = new int[][]
|
private static int[][] _directions = new int[][]
|
||||||
{
|
{
|
||||||
new int[] {1, 0}, // 수직
|
new int[] {1, 0}, // 수직
|
||||||
@ -168,6 +188,7 @@ public class GameLogic : MonoBehaviour
|
|||||||
_board = new Enums.PlayerType[15, 15];
|
_board = new Enums.PlayerType[15, 15];
|
||||||
this.stoneController = stoneController;
|
this.stoneController = stoneController;
|
||||||
this.gameType = gameType;
|
this.gameType = gameType;
|
||||||
|
_totalStoneCounter = 0;
|
||||||
|
|
||||||
selectedRow = -1;
|
selectedRow = -1;
|
||||||
selectedCol = -1;
|
selectedCol = -1;
|
||||||
@ -204,13 +225,12 @@ public class GameLogic : MonoBehaviour
|
|||||||
|
|
||||||
//TODO: 기보 매니저에게 플레이어 닉네임 넘겨주기, 프로필정보도 넘겨줘야 합니다.
|
//TODO: 기보 매니저에게 플레이어 닉네임 넘겨주기, 프로필정보도 넘겨줘야 합니다.
|
||||||
ReplayManager.Instance.InitReplayData("PlayerA","nicknameB");
|
ReplayManager.Instance.InitReplayData("PlayerA","nicknameB");
|
||||||
|
|
||||||
|
|
||||||
switch (gameType)
|
switch (gameType)
|
||||||
{
|
{
|
||||||
case Enums.GameType.SinglePlay:
|
case Enums.GameType.SinglePlay:
|
||||||
firstPlayerState = new PlayerState(true);
|
firstPlayerState = new PlayerState(true);
|
||||||
secondPlayerState = new PlayerState(false);
|
secondPlayerState = new AIState();
|
||||||
SetState(firstPlayerState);
|
SetState(firstPlayerState);
|
||||||
break;
|
break;
|
||||||
case Enums.GameType.MultiPlay:
|
case Enums.GameType.MultiPlay:
|
||||||
@ -221,6 +241,12 @@ public class GameLogic : MonoBehaviour
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//돌 카운터 증가 함수
|
||||||
|
public void CountStoneCounter()
|
||||||
|
{
|
||||||
|
_totalStoneCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
//착수 버튼 클릭시 호출되는 함수
|
//착수 버튼 클릭시 호출되는 함수
|
||||||
public void OnConfirm()
|
public void OnConfirm()
|
||||||
{
|
{
|
||||||
@ -288,6 +314,7 @@ public class GameLogic : MonoBehaviour
|
|||||||
LastNSelectedSetting(row, col);
|
LastNSelectedSetting(row, col);
|
||||||
|
|
||||||
ReplayManager.Instance.RecordStonePlaced(Enums.StoneType.White, row, col);
|
ReplayManager.Instance.RecordStonePlaced(Enums.StoneType.White, row, col);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -319,7 +346,7 @@ public class GameLogic : MonoBehaviour
|
|||||||
public void EndGame()
|
public void EndGame()
|
||||||
{
|
{
|
||||||
SetState(null);
|
SetState(null);
|
||||||
|
//TODO: 게임 종료 후 행동 구현
|
||||||
}
|
}
|
||||||
|
|
||||||
//승리 확인 함수
|
//승리 확인 함수
|
||||||
@ -330,7 +357,7 @@ public class GameLogic : MonoBehaviour
|
|||||||
var (count, _) = CountStones(_board, row, col, dir, player);
|
var (count, _) = CountStones(_board, row, col, dir, player);
|
||||||
|
|
||||||
// 자기 자신 포함하여 5개 이상일 시 true 반환
|
// 자기 자신 포함하여 5개 이상일 시 true 반환
|
||||||
if (count + 1 >= WIN_COUNT)
|
if (count + 1 >= Constants.WIN_COUNT)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,7 +403,56 @@ public class GameLogic : MonoBehaviour
|
|||||||
return (count, openEnds);
|
return (count, openEnds);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Renju Rule Detector
|
public Enums.PlayerType[,] GetBoard()
|
||||||
|
{
|
||||||
|
return _board;
|
||||||
|
}
|
||||||
|
//무승부 확인
|
||||||
|
public bool CheckGameDraw()
|
||||||
|
{
|
||||||
|
if (CheckIsFull(_board)) return true; // 빈 칸이 없으면 무승부
|
||||||
|
bool playerAHasChance = CheckFiveChance(_board, Enums.PlayerType.PlayerA);
|
||||||
|
bool playerBHasChance = CheckFiveChance(_board, Enums.PlayerType.PlayerB);
|
||||||
|
return !(playerAHasChance || playerBHasChance); // 둘 다 기회가 없으면 무승부
|
||||||
|
}
|
||||||
|
|
||||||
|
//연속되는 5개가 만들어질 기회가 있는지 판단
|
||||||
|
private bool CheckFiveChance(Enums.PlayerType[,] board, Enums.PlayerType player)
|
||||||
|
{
|
||||||
|
var tempBoard = (Enums.PlayerType[,])board.Clone();
|
||||||
|
int size = board.GetLength(0);
|
||||||
|
for (int row = 0; row < size; row++)
|
||||||
|
{
|
||||||
|
for (int col = 0; col < size; col++)
|
||||||
|
{
|
||||||
|
if (tempBoard[row, col] != Enums.PlayerType.None) continue;
|
||||||
|
tempBoard[row, col] = player;
|
||||||
|
foreach (var dir in _directions)
|
||||||
|
{
|
||||||
|
var (count, _) = CountStones(tempBoard, row, col, dir, player);
|
||||||
|
|
||||||
|
// 자기 자신 포함하여 5개 이상일 시 true 반환
|
||||||
|
if (count + 1 >= Constants.WIN_COUNT) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//보드가 꽉 찼는지 확인
|
||||||
|
private static bool CheckIsFull(Enums.PlayerType[,] board)
|
||||||
|
{
|
||||||
|
int size = board.GetLength(0);
|
||||||
|
for (int row = 0; row < size; row++)
|
||||||
|
{
|
||||||
|
for (int col = 0; col < size; col++)
|
||||||
|
{
|
||||||
|
if (board[row, col] == Enums.PlayerType.None) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Renju Rule Detector
|
||||||
// 금수 위치 업데이트 및 표시
|
// 금수 위치 업데이트 및 표시
|
||||||
private void UpdateForbiddenMoves()
|
private void UpdateForbiddenMoves()
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,6 @@ using System.Collections;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
[RequireComponent(typeof(AudioSource))]
|
|
||||||
public class GameManager : Singleton<GameManager>
|
public class GameManager : Singleton<GameManager>
|
||||||
{
|
{
|
||||||
private Enums.GameType _gameType;
|
private Enums.GameType _gameType;
|
||||||
@ -51,7 +50,6 @@ public class GameManager : Singleton<GameManager>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Log("착수 위치를 선택 해주세요");
|
|
||||||
//TODO: 착수할 위치를 선택하라는 동작
|
//TODO: 착수할 위치를 선택하라는 동작
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using TMPro;
|
using TMPro;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Serialization;
|
using UnityEngine.Serialization;
|
||||||
@ -83,4 +84,42 @@ public class MainPanelController : MonoBehaviour
|
|||||||
{
|
{
|
||||||
GameManager.Instance.ChangeToGameScene(Enums.GameType.SinglePlay);
|
GameManager.Instance.ChangeToGameScene(Enums.GameType.SinglePlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//상점 패널 생성
|
||||||
|
public void OnShopButtonClick()
|
||||||
|
{
|
||||||
|
List<ShopItem> shopItems = new List<ShopItem>(); //상점 데이터 리스트 생성
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
if (i == 0) //광고 항목
|
||||||
|
{
|
||||||
|
ShopItem shopItem = new ShopItem
|
||||||
|
{
|
||||||
|
name = "광고) 코인500개 ",
|
||||||
|
price = 0
|
||||||
|
};
|
||||||
|
shopItems.Add(shopItem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ShopItem shopItem = new ShopItem
|
||||||
|
{
|
||||||
|
name = i*1000+"개 ",
|
||||||
|
price = i * 1000
|
||||||
|
};
|
||||||
|
shopItems.Add(shopItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GameManager.Instance.panelManager.OpenShopPanel(shopItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenReplayButtonClick()
|
||||||
|
{
|
||||||
|
GameManager.Instance.panelManager.OpenReplayPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenSettingButtonClick()
|
||||||
|
{
|
||||||
|
GameManager.Instance.panelManager.OpenSettingsPanel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using UnityEngine.Networking;
|
using UnityEngine.Networking;
|
||||||
@ -47,7 +48,6 @@ public class NetworkManager : Singleton<NetworkManager>
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var result = www.downloadHandler.text;
|
var result = www.downloadHandler.text;
|
||||||
success?.Invoke();
|
|
||||||
|
|
||||||
// 회원가입 성공 팝업 표시
|
// 회원가입 성공 팝업 표시
|
||||||
GameManager.Instance.panelManager.OpenConfirmPanel("회원 가입이 완료 되었습니다.", () =>
|
GameManager.Instance.panelManager.OpenConfirmPanel("회원 가입이 완료 되었습니다.", () =>
|
||||||
@ -385,7 +385,7 @@ public class NetworkManager : Singleton<NetworkManager>
|
|||||||
/// <param name="paymentType">결제타입(카드,구글페이)</param>
|
/// <param name="paymentType">결제타입(카드,구글페이)</param>
|
||||||
/// <param name="success"></param>
|
/// <param name="success"></param>
|
||||||
/// <param name="failure"></param>
|
/// <param name="failure"></param>
|
||||||
public void PurchaseCoins(int amount, string paymentId, string paymentType, Action<int> success, Action failure)
|
public void PurchaseCoins(int amount, string paymentId, string paymentType, Action<int> success, Action failure)
|
||||||
{
|
{
|
||||||
StartCoroutine(PurchaseCoinsCoroutine(amount, paymentId, paymentType, success, failure));
|
StartCoroutine(PurchaseCoinsCoroutine(amount, paymentId, paymentType, success, failure));
|
||||||
}
|
}
|
||||||
@ -395,10 +395,10 @@ public class NetworkManager : Singleton<NetworkManager>
|
|||||||
string url = Constants.ServerURL + "/coins/purchase"; // 서버 엔드포인트
|
string url = Constants.ServerURL + "/coins/purchase"; // 서버 엔드포인트
|
||||||
PurchaseData purchaseData = new PurchaseData(amount, paymentId, paymentType);
|
PurchaseData purchaseData = new PurchaseData(amount, paymentId, paymentType);
|
||||||
string jsonString = JsonUtility.ToJson(purchaseData);
|
string jsonString = JsonUtility.ToJson(purchaseData);
|
||||||
|
byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonString);
|
||||||
|
|
||||||
using (UnityWebRequest www = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST))
|
using (UnityWebRequest www = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST))
|
||||||
{
|
{
|
||||||
byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonString);
|
|
||||||
www.uploadHandler = new UploadHandlerRaw(bodyRaw);
|
www.uploadHandler = new UploadHandlerRaw(bodyRaw);
|
||||||
www.downloadHandler = new DownloadHandlerBuffer();
|
www.downloadHandler = new DownloadHandlerBuffer();
|
||||||
www.SetRequestHeader("Content-Type", "application/json");
|
www.SetRequestHeader("Content-Type", "application/json");
|
||||||
@ -445,4 +445,36 @@ public class NetworkManager : Singleton<NetworkManager>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void GetLeaderboardData(Action<List<ScoreInfo>> success, Action failure)
|
||||||
|
{
|
||||||
|
StartCoroutine(GetLeaderboardDataCoroutine(success, failure));
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator GetLeaderboardDataCoroutine(Action<List<ScoreInfo>> success, Action failure)
|
||||||
|
{
|
||||||
|
string url = Constants.ServerURL + "/leaderboard/"; // 서버의 리더보드 데이터 URL
|
||||||
|
|
||||||
|
UnityWebRequest www = UnityWebRequest.Get(url); // GET 요청으로 데이터 받기
|
||||||
|
yield return www.SendWebRequest(); // 요청 전송 대기
|
||||||
|
|
||||||
|
// 요청이 실패했을 때
|
||||||
|
if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError)
|
||||||
|
{
|
||||||
|
Debug.LogError("Error: " + www.error);
|
||||||
|
failure?.Invoke();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 성공적으로 데이터를 받아온 경우
|
||||||
|
string jsonResponse = www.downloadHandler.text; // 응답으로 받은 JSON 데이터
|
||||||
|
|
||||||
|
// JSON을 ScoreInfo 리스트로 파싱
|
||||||
|
ScoreListWrapper wrapper = JsonUtility.FromJson<ScoreListWrapper>(jsonResponse);
|
||||||
|
List<ScoreInfo> leaderboardItems = wrapper.leaderboardDatas;
|
||||||
|
|
||||||
|
// Show 메서드를 통해 데이터를 표시
|
||||||
|
success?.Invoke(leaderboardItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -23,9 +23,9 @@ public class ScoreCellController : MonoBehaviour
|
|||||||
winText.text = item.win.ToString();
|
winText.text = item.win.ToString();
|
||||||
loseText.text = item.lose.ToString();
|
loseText.text = item.lose.ToString();
|
||||||
|
|
||||||
if (profileImage != null && item.profileImageIndex != null)
|
if (profileImage != null)
|
||||||
{
|
{
|
||||||
profileImage.sprite = profileSprites[item.profileImageIndex]; // 프로필 이미지 (Sprite 할당)
|
profileImage.sprite = profileSprites[item.imageIndex]; // 프로필 이미지 (Sprite 할당)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,9 +2,10 @@ using System;
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.Serialization;
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class ScoreListWrapper
|
public class ScoreListWrapper
|
||||||
{
|
{
|
||||||
public List<ScoreInfo> scoreInfos; // 여러 개의 ScoreInfo를 담을 리스트
|
public List<ScoreInfo> leaderboardDatas; // 여러 개의 ScoreInfo를 담을 리스트
|
||||||
}
|
}
|
@ -29,7 +29,7 @@ public struct ScoreInfo
|
|||||||
public int win;
|
public int win;
|
||||||
public int lose;
|
public int lose;
|
||||||
public int totalGames;
|
public int totalGames;
|
||||||
public int profileImageIndex;
|
public int imageIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
@ -43,8 +43,13 @@ public class SigninPanelController : MonoBehaviour
|
|||||||
[SerializeField] private TMP_InputField emailInputField;
|
[SerializeField] private TMP_InputField emailInputField;
|
||||||
[SerializeField] private TMP_InputField passwordInputField;
|
[SerializeField] private TMP_InputField passwordInputField;
|
||||||
|
|
||||||
[SerializeField] private MainPanelManager mainPanel;
|
private MainPanelManager mainPanel;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
if (mainPanel == null) mainPanel = FindObjectOfType<MainPanelManager>();
|
||||||
|
}
|
||||||
|
|
||||||
public void OnClickSigninButton()
|
public void OnClickSigninButton()
|
||||||
{
|
{
|
||||||
string email = emailInputField.text;
|
string email = emailInputField.text;
|
||||||
@ -60,13 +65,13 @@ public class SigninPanelController : MonoBehaviour
|
|||||||
|
|
||||||
NetworkManager.Instance.Signin(signinData, (signinResult) =>
|
NetworkManager.Instance.Signin(signinData, (signinResult) =>
|
||||||
{
|
{
|
||||||
Destroy(gameObject);
|
|
||||||
|
|
||||||
// 유저 정보 저장
|
// 유저 정보 저장
|
||||||
UserManager.Instance.SetUserInfo(signinResult);
|
UserManager.Instance.SetUserInfo(signinResult);
|
||||||
|
|
||||||
// 메인 패널 정보 갱신
|
// 메인 패널 정보 갱신
|
||||||
mainPanel.UpdateMainPanelUI(GameManager.Instance.panelManager.OpenMainPanel);
|
mainPanel.UpdateMainPanelUI(GameManager.Instance.panelManager.OpenMainPanel);
|
||||||
|
|
||||||
|
Destroy(gameObject);
|
||||||
}, result =>
|
}, result =>
|
||||||
{
|
{
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
|
@ -1,9 +1,20 @@
|
|||||||
public class ForbiddenDetectorBase
|
public class ForbiddenDetectorBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 흑색 돌
|
||||||
|
/// </summary>
|
||||||
private protected Enums.PlayerType Black = Enums.PlayerType.PlayerA;
|
private protected Enums.PlayerType Black = Enums.PlayerType.PlayerA;
|
||||||
|
/// <summary>
|
||||||
|
/// 빈칸
|
||||||
|
/// </summary>
|
||||||
private protected Enums.PlayerType Space = Enums.PlayerType.None;
|
private protected Enums.PlayerType Space = Enums.PlayerType.None;
|
||||||
|
/// <summary>
|
||||||
// 8방향을 나타내는 델타 배열 (가로, 세로, 대각선 방향)
|
/// 흰색 돌, 렌주룰 내에선 벽으로도 활용
|
||||||
|
/// </summary>
|
||||||
|
private protected Enums.PlayerType White = Enums.PlayerType.PlayerB;
|
||||||
|
/// <summary>
|
||||||
|
/// 8방향을 나타내는 델타 배열 (가로, 세로, 대각선 방향)
|
||||||
|
/// </summary>
|
||||||
private protected readonly int[,] Directions = new int[8, 2]
|
private protected readonly int[,] Directions = new int[8, 2]
|
||||||
{
|
{
|
||||||
{ 1, 0 }, // 오른쪽
|
{ 1, 0 }, // 오른쪽
|
||||||
@ -16,11 +27,13 @@
|
|||||||
{ 1, -1 } // 오른쪽 위
|
{ 1, -1 } // 오른쪽 위
|
||||||
};
|
};
|
||||||
|
|
||||||
// 방향 쌍을 정의 (반대 방향끼리 쌍을 이룸)
|
/// <summary>
|
||||||
// 0-4: 가로 방향 쌍 (동-서)
|
/// 방향 쌍을 정의 (반대 방향끼리 쌍을 이룸)
|
||||||
// 1-5: 대각선 방향 쌍 (남동-북서)
|
/// 0-4: 가로 방향 쌍 (동-서)
|
||||||
// 2-6: 세로 방향 쌍 (남-북)
|
/// 1-5: 대각선 방향 쌍 (남동-북서)
|
||||||
// 3-7: 대각선 방향 쌍 (남서-북동)
|
/// 2-6: 세로 방향 쌍 (남-북)
|
||||||
|
/// 3-7: 대각선 방향 쌍 (남서-북동)
|
||||||
|
/// </summary>
|
||||||
private protected readonly int[,] DirectionPairs = { { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 } };
|
private protected readonly int[,] DirectionPairs = { { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 } };
|
||||||
|
|
||||||
// 15*15 보드 사이즈
|
// 15*15 보드 사이즈
|
||||||
|
@ -30,12 +30,9 @@ public class RenjuDoubleFourDetector: ForbiddenDetectorBase
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private bool CheckDoubleFour(Enums.PlayerType[,] board, int row, int col)
|
private bool CheckDoubleFour(Enums.PlayerType[,] board, int row, int col)
|
||||||
{
|
{
|
||||||
// 각각 두개의 라인에서 쌍사를 형성하는 경우
|
|
||||||
if (FindDoubleLineFour(board, row, col)) return true;
|
|
||||||
|
|
||||||
// true : 일직선으로 쌍사가 만들어지는 특수 패턴
|
|
||||||
// false : 모든 경우에도 쌍사가 만들어지지 않음
|
// false : 모든 경우에도 쌍사가 만들어지지 않음
|
||||||
return FindSingleLineDoubleFour(board, row, col);
|
return FindDoubleLineFour(board, row, col) || // 각각 두개의 라인에서 쌍사를 형성하는 경우
|
||||||
|
FindSingleLineDoubleFour(board, row, col); // 일직선으로 쌍사가 만들어지는 특수 패턴
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool FindDoubleLineFour(Enums.PlayerType[,] board, int row, int col)
|
private bool FindDoubleLineFour(Enums.PlayerType[,] board, int row, int col)
|
||||||
@ -136,7 +133,7 @@ public class RenjuDoubleFourDetector: ForbiddenDetectorBase
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
linePattern[centerIndex + i] = Space; // 범위 밖은 빈칸으로 처리
|
linePattern[centerIndex + i] = White; // 범위 밖은 백돌로 처리
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +149,7 @@ public class RenjuDoubleFourDetector: ForbiddenDetectorBase
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
linePattern[centerIndex - i] = Space; // 범위 밖은 빈칸으로 처리
|
linePattern[centerIndex - i] = White; // 범위 밖은 백돌로 처리
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,7 +178,7 @@ public class RenjuDoubleFourDetector: ForbiddenDetectorBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 정확히 4개의 돌이 있고, 1개의 빈칸이 있으면 4로 판정
|
// 4개의 돌이 있고, 1개의 빈칸이 있으면 4로 판정
|
||||||
// (현재 위치는 흑으로 이미 설정되어 있음)
|
// (현재 위치는 흑으로 이미 설정되어 있음)
|
||||||
if (stoneCount == 4)
|
if (stoneCount == 4)
|
||||||
{
|
{
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 0daf1f2b8cbe4b19adc0e42db7a15991
|
guid: f997e95272e950240a6e9e2f8a99fdfa
|
||||||
timeCreated: 1742270734
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
@ -1,8 +1,25 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class RenjuDoubleThreeDetector: ForbiddenDetectorBase
|
/// <summary>
|
||||||
|
/// 렌주 쌍삼(3-3) 금수 판정을 위한 개선된 클래스
|
||||||
|
/// 렌주 국제 규칙 9.3에 따라 쌍삼의 예외 상황까지 정확히 판별
|
||||||
|
/// </summary>
|
||||||
|
public class RenjuDoubleThreeDetector : ForbiddenDetectorBase
|
||||||
{
|
{
|
||||||
|
// 열린 3 패턴 정보를 저장하는 구조체
|
||||||
|
private struct OpenThreeInfo
|
||||||
|
{
|
||||||
|
public int direction; // 방향 인덱스
|
||||||
|
public List<Vector2Int> emptyPositions; // 빈 좌표들 (4를 만들 수 있는 위치)
|
||||||
|
|
||||||
|
public OpenThreeInfo(int dir)
|
||||||
|
{
|
||||||
|
direction = dir;
|
||||||
|
emptyPositions = new List<Vector2Int>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 쌍삼(3-3) 여부를 검사합니다.
|
/// 쌍삼(3-3) 여부를 검사합니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -15,12 +32,635 @@ public class RenjuDoubleThreeDetector: ForbiddenDetectorBase
|
|||||||
// 임시로 돌 배치
|
// 임시로 돌 배치
|
||||||
board[row, col] = Black;
|
board[row, col] = Black;
|
||||||
|
|
||||||
// 쌍삼 검사
|
// 쌍삼 기본 검사 (열린 3이 2개 이상인지)
|
||||||
// bool isThreeThree = CheckThreeThree(board, row, col);
|
List<OpenThreeInfo> openThrees = FindAllOpenThrees(board, row, col);
|
||||||
|
|
||||||
// 원래 상태로 되돌림
|
// 원래 상태로 되돌림
|
||||||
board[row, col] = Space;
|
board[row, col] = Space;
|
||||||
|
|
||||||
|
// 열린 3이 2개 미만이면 쌍삼이 아님
|
||||||
|
if (openThrees.Count < 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 렌주 규칙 9.3에 따른 예외 케이스 확인
|
||||||
|
return !CheckDoubleThreeExceptions(board, row, col, openThrees);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 모든 방향에서 열린 3을 찾아 반환합니다.
|
||||||
|
/// </summary>
|
||||||
|
private List<OpenThreeInfo> FindAllOpenThrees(Enums.PlayerType[,] board, int row, int col)
|
||||||
|
{
|
||||||
|
List<OpenThreeInfo> openThrees = new List<OpenThreeInfo>();
|
||||||
|
|
||||||
|
// 4개의 방향 쌍에 대해 검사 (대각선 및 직선 포함)
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
int dir1 = DirectionPairs[i, 0];
|
||||||
|
int dir2 = DirectionPairs[i, 1];
|
||||||
|
|
||||||
|
// 열린 3 정보 획득
|
||||||
|
OpenThreeInfo threeInfo = new OpenThreeInfo(i);
|
||||||
|
if (FindOpenThreeInDirection(board, row, col, dir1, dir2, ref threeInfo))
|
||||||
|
{
|
||||||
|
openThrees.Add(threeInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return openThrees;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 특정 방향에서 열린 3을 찾고 관련 정보를 채웁니다.
|
||||||
|
/// </summary>
|
||||||
|
private bool FindOpenThreeInDirection(Enums.PlayerType[,] board, int row, int col, int dir1, int dir2, ref OpenThreeInfo threeInfo)
|
||||||
|
{
|
||||||
|
// 라인 패턴 추출
|
||||||
|
Enums.PlayerType[] linePattern = ExtractLinePattern(board, row, col, dir1, dir2);
|
||||||
|
int centerIndex = 5; // 중앙 인덱스 (현재 위치)
|
||||||
|
|
||||||
|
// 연속된 열린 3 또는 한 칸 떨어진 열린 3 확인
|
||||||
|
if (FindConsecutiveOpenThree(linePattern, centerIndex, ref threeInfo, row, col, dir1, dir2) ||
|
||||||
|
FindGappedOpenThree(linePattern, centerIndex, ref threeInfo, row, col, dir1, dir2))
|
||||||
|
{
|
||||||
|
// 열린 3이 발견됨
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 라인 패턴을 추출합니다.
|
||||||
|
/// </summary>
|
||||||
|
private Enums.PlayerType[] ExtractLinePattern(Enums.PlayerType[,] board, int row, int col, int dir1, int dir2)
|
||||||
|
{
|
||||||
|
Enums.PlayerType[] linePattern = new Enums.PlayerType[11];
|
||||||
|
int centerIndex = 5; // 중앙 인덱스 (현재 위치)
|
||||||
|
|
||||||
|
// 현재 위치 설정
|
||||||
|
linePattern[centerIndex] = Black;
|
||||||
|
|
||||||
|
// dir1 방향으로 패턴 채우기
|
||||||
|
for (int i = 1; i <= 5; i++)
|
||||||
|
{
|
||||||
|
int newRow = row + Directions[dir1, 0] * i;
|
||||||
|
int newCol = col + Directions[dir1, 1] * i;
|
||||||
|
|
||||||
|
if (IsInBounds(newRow, newCol))
|
||||||
|
{
|
||||||
|
linePattern[centerIndex + i] = board[newRow, newCol];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
linePattern[centerIndex + i] = White; // 범위 밖은 벽으로 처리하여 일관성 유지
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dir2 방향으로 패턴 채우기
|
||||||
|
for (int i = 1; i <= 5; i++)
|
||||||
|
{
|
||||||
|
int newRow = row + Directions[dir2, 0] * i;
|
||||||
|
int newCol = col + Directions[dir2, 1] * i;
|
||||||
|
|
||||||
|
if (IsInBounds(newRow, newCol))
|
||||||
|
{
|
||||||
|
linePattern[centerIndex - i] = board[newRow, newCol];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
linePattern[centerIndex - i] = White; // 범위 밖은 벽으로 처리하여 일관성 유지
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return linePattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 연속된 열린 3 패턴을 찾고 관련 정보를 채웁니다.
|
||||||
|
/// </summary>
|
||||||
|
private bool FindConsecutiveOpenThree(Enums.PlayerType[] linePattern, int centerIndex, ref OpenThreeInfo threeInfo, int row, int col, int dir1, int dir2)
|
||||||
|
{
|
||||||
|
// 연속된 3개의 돌 패턴 (●●●)
|
||||||
|
for (int start = centerIndex - 2; start <= centerIndex; start++)
|
||||||
|
{
|
||||||
|
// 범위 체크
|
||||||
|
if (start < 0 || start + 2 >= linePattern.Length)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3개의 연속된 돌 확인
|
||||||
|
bool isConsecutiveThree = true;
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (linePattern[start + i] != Black)
|
||||||
|
{
|
||||||
|
isConsecutiveThree = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isConsecutiveThree)
|
||||||
|
{
|
||||||
|
// 양쪽이 모두 열려있는지 확인
|
||||||
|
bool isLeftOpen = (start - 1 >= 0) && (linePattern[start - 1] == Space);
|
||||||
|
bool isRightOpen = (start + 3 < linePattern.Length) && (linePattern[start + 3] == Space);
|
||||||
|
|
||||||
|
// 양쪽이 모두 열려있으면 열린 3
|
||||||
|
if (isLeftOpen && isRightOpen)
|
||||||
|
{
|
||||||
|
// 추가 검증: 더 확장해서 열려있는지 확인
|
||||||
|
bool isExtendedLeftOpen = IsExtendedOpen(linePattern, start - 1, -1);
|
||||||
|
bool isExtendedRightOpen = IsExtendedOpen(linePattern, start + 3, 1);
|
||||||
|
|
||||||
|
if (isExtendedLeftOpen && isExtendedRightOpen)
|
||||||
|
{
|
||||||
|
// 4를 만들 수 있는 위치 저장
|
||||||
|
if (isLeftOpen)
|
||||||
|
{
|
||||||
|
int leftRow = row + Directions[dir2, 0] * (centerIndex - (start - 1));
|
||||||
|
int leftCol = col + Directions[dir2, 1] * (centerIndex - (start - 1));
|
||||||
|
if (IsInBounds(leftRow, leftCol))
|
||||||
|
{
|
||||||
|
threeInfo.emptyPositions.Add(new Vector2Int(leftCol, leftRow));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRightOpen)
|
||||||
|
{
|
||||||
|
int rightRow = row + Directions[dir1, 0] * ((start + 3) - centerIndex);
|
||||||
|
int rightCol = col + Directions[dir1, 1] * ((start + 3) - centerIndex);
|
||||||
|
if (IsInBounds(rightRow, rightCol))
|
||||||
|
{
|
||||||
|
threeInfo.emptyPositions.Add(new Vector2Int(rightCol, rightRow));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 한 칸 떨어진 열린 3 패턴을 찾고 관련 정보를 채웁니다.
|
||||||
|
/// </summary>
|
||||||
|
private bool FindGappedOpenThree(Enums.PlayerType[] linePattern, int centerIndex, ref OpenThreeInfo threeInfo, int row, int col, int dir1, int dir2)
|
||||||
|
{
|
||||||
|
// 한 칸 떨어진 패턴 확인 (●●○● 또는 ●○●●)
|
||||||
|
for (int start = Mathf.Max(0, centerIndex - 3); start <= Mathf.Min(linePattern.Length - 4, centerIndex); start++)
|
||||||
|
{
|
||||||
|
// 패턴 내에 돌과 빈칸 개수 확인
|
||||||
|
int stoneCount = 0;
|
||||||
|
int gapCount = 0;
|
||||||
|
int gapPosition = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (linePattern[start + i] == Black)
|
||||||
|
{
|
||||||
|
stoneCount++;
|
||||||
|
}
|
||||||
|
else if (linePattern[start + i] == Space)
|
||||||
|
{
|
||||||
|
gapCount++;
|
||||||
|
gapPosition = start + i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 상대 돌이나 벽이 있으면 패턴이 깨짐
|
||||||
|
stoneCount = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3개의 돌과 1개의 빈칸으로 구성된 패턴
|
||||||
|
if (stoneCount == 3 && gapCount == 1)
|
||||||
|
{
|
||||||
|
// 양쪽이 모두 열려있는지 확인
|
||||||
|
bool isLeftOpen = (start - 1 >= 0) && (linePattern[start - 1] == Space);
|
||||||
|
bool isRightOpen = (start + 4 < linePattern.Length) && (linePattern[start + 4] == Space);
|
||||||
|
|
||||||
|
// 한쪽이라도 열려있으면 잠재적 열린 3
|
||||||
|
if (isLeftOpen || isRightOpen)
|
||||||
|
{
|
||||||
|
// 빈칸에 돌을 놓았을 때 열린 4가 되는지 확인
|
||||||
|
if (CheckIfCreatesOpenFour(linePattern, gapPosition))
|
||||||
|
{
|
||||||
|
// 4를 만들 수 있는 위치 저장 (빈칸 위치)
|
||||||
|
int gapRow = row;
|
||||||
|
int gapCol = col;
|
||||||
|
|
||||||
|
// 빈칸의 보드 좌표 계산
|
||||||
|
int offset = gapPosition - centerIndex;
|
||||||
|
if (offset > 0)
|
||||||
|
{
|
||||||
|
gapRow += Directions[dir1, 0] * offset;
|
||||||
|
gapCol += Directions[dir1, 1] * offset;
|
||||||
|
}
|
||||||
|
else if (offset < 0)
|
||||||
|
{
|
||||||
|
gapRow += Directions[dir2, 0] * (-offset);
|
||||||
|
gapCol += Directions[dir2, 1] * (-offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsInBounds(gapRow, gapCol))
|
||||||
|
{
|
||||||
|
threeInfo.emptyPositions.Add(new Vector2Int(gapCol, gapRow));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 장목이 되는지 확인 (장목이 되면 열린 3이 아님)
|
||||||
|
if (CheckIfCreatesOverline(linePattern, gapPosition))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 특정 방향으로 추가로 열려있는지 확인합니다.
|
||||||
|
/// </summary>
|
||||||
|
private bool IsExtendedOpen(Enums.PlayerType[] linePattern, int startPos, int direction)
|
||||||
|
{
|
||||||
|
// 한 칸 더 확장해서 확인
|
||||||
|
int nextPos = startPos + direction;
|
||||||
|
if (nextPos >= 0 && nextPos < linePattern.Length)
|
||||||
|
{
|
||||||
|
// 다음 칸이 상대 돌이나 벽이면 확장 불가
|
||||||
|
if (linePattern[nextPos] == White)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 범위를 벗어나면 확장 불가
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 빈칸에 돌을 놓았을 때 열린 4가 되는지 확인합니다.
|
||||||
|
/// </summary>
|
||||||
|
private bool CheckIfCreatesOpenFour(Enums.PlayerType[] linePattern, int position)
|
||||||
|
{
|
||||||
|
// 시뮬레이션: 빈칸에 돌을 놓아봄
|
||||||
|
Enums.PlayerType[] testPattern = new Enums.PlayerType[linePattern.Length];
|
||||||
|
System.Array.Copy(linePattern, testPattern, linePattern.Length);
|
||||||
|
testPattern[position] = Black;
|
||||||
|
|
||||||
|
// 놓은 위치를 포함해 연속된 4가 있는지 확인
|
||||||
|
for (int start = Mathf.Max(0, position - 3); start <= position; start++)
|
||||||
|
{
|
||||||
|
// 범위 체크
|
||||||
|
if (start + 3 >= testPattern.Length)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4개의 연속된 돌 확인
|
||||||
|
bool isConsecutiveFour = true;
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (testPattern[start + i] != Black)
|
||||||
|
{
|
||||||
|
isConsecutiveFour = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isConsecutiveFour)
|
||||||
|
{
|
||||||
|
// 양쪽이 모두 열려있는지 확인 (열린 4)
|
||||||
|
bool isLeftOpen = (start - 1 >= 0) && (testPattern[start - 1] == Space);
|
||||||
|
bool isRightOpen = (start + 4 < testPattern.Length) && (testPattern[start + 4] == Space);
|
||||||
|
|
||||||
|
if (isLeftOpen || isRightOpen)
|
||||||
|
{
|
||||||
|
return true; // 열린 4나 반열린 4가 됨
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 빈칸에 돌을 놓았을 때 장목(6목 이상)이 되는지 확인합니다.
|
||||||
|
/// </summary>
|
||||||
|
private bool CheckIfCreatesOverline(Enums.PlayerType[] linePattern, int position)
|
||||||
|
{
|
||||||
|
// 시뮬레이션: 빈칸에 돌을 놓아봄
|
||||||
|
Enums.PlayerType[] testPattern = new Enums.PlayerType[linePattern.Length];
|
||||||
|
System.Array.Copy(linePattern, testPattern, linePattern.Length);
|
||||||
|
testPattern[position] = Black;
|
||||||
|
|
||||||
|
// 놓은 위치 주변의 최대 연속 돌 수 계산
|
||||||
|
int maxLength = 1; // 놓은 돌 포함
|
||||||
|
|
||||||
|
// 오른쪽 방향 연속 돌 세기
|
||||||
|
for (int i = position + 1; i < testPattern.Length && testPattern[i] == Black; i++)
|
||||||
|
{
|
||||||
|
maxLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 왼쪽 방향 연속 돌 세기
|
||||||
|
for (int i = position - 1; i >= 0 && testPattern[i] == Black; i--)
|
||||||
|
{
|
||||||
|
maxLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6목 이상이면 장목
|
||||||
|
return maxLength >= 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 렌주 규칙 9.3에 따른 쌍삼 예외 케이스를 확인합니다.
|
||||||
|
/// </summary>
|
||||||
|
private bool CheckDoubleThreeExceptions(Enums.PlayerType[,] board, int row, int col, List<OpenThreeInfo> openThrees)
|
||||||
|
{
|
||||||
|
// 예외 케이스 1: 하나의 삼만 열린 사가 될 수 있는 경우 (9.3 a항)
|
||||||
|
bool canFormOpenFourWithoutDoubleFour = CheckExceptionCanFormOneFour(board, row, col, openThrees);
|
||||||
|
|
||||||
|
// 예외 케이스 2: 9.3 b항 (복잡한 연쇄 체크)
|
||||||
|
bool isMeetExceptionB = CheckExceptionB(board, row, col, openThrees);
|
||||||
|
|
||||||
|
// 어느 하나라도 예외 조건을 만족하면 쌍삼이 아님
|
||||||
|
return canFormOpenFourWithoutDoubleFour || isMeetExceptionB;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 예외 케이스 1: 하나의 삼만 열린 사가 될 수 있고 쌍사가 형성되지 않는 경우 (9.3 a항)
|
||||||
|
/// </summary>
|
||||||
|
private bool CheckExceptionCanFormOneFour(Enums.PlayerType[,] board, int row, int col, List<OpenThreeInfo> openThrees)
|
||||||
|
{
|
||||||
|
int canFormFourCount = 0;
|
||||||
|
|
||||||
|
// 각 열린 3에 대해, 4를 만들 수 있는지 확인
|
||||||
|
foreach (var threeInfo in openThrees)
|
||||||
|
{
|
||||||
|
foreach (var emptyPos in threeInfo.emptyPositions)
|
||||||
|
{
|
||||||
|
// 빈 위치에 돌을 놓았을 때 열린 4가 되는지 확인
|
||||||
|
board[emptyPos.y, emptyPos.x] = Black;
|
||||||
|
|
||||||
|
// 쌍사가 형성되는지 확인
|
||||||
|
bool formsDoubleFour = CheckDoubleFour(board, emptyPos.y, emptyPos.x);
|
||||||
|
|
||||||
|
// 원래 상태로 복원
|
||||||
|
board[emptyPos.y, emptyPos.x] = Space;
|
||||||
|
|
||||||
|
// 쌍사 없이 4를 만들 수 있으면 카운트 증가
|
||||||
|
if (!formsDoubleFour)
|
||||||
|
{
|
||||||
|
canFormFourCount++;
|
||||||
|
// 디버깅
|
||||||
|
// Debug.Log($"Can form four at ({emptyPos.x}, {emptyPos.y}) without double four");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 하나의 삼만 쌍사 없이 4로 만들 수 있는 경우
|
||||||
|
return canFormFourCount == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 예외 케이스 2: 9.3 b항의 복잡한 연쇄 체크
|
||||||
|
/// </summary>
|
||||||
|
private bool CheckExceptionB(Enums.PlayerType[,] board, int row, int col, List<OpenThreeInfo> openThrees)
|
||||||
|
{
|
||||||
|
// 이 부분은 매우 복잡한 렌주 규칙 9.3 b항을 구현해야 합니다.
|
||||||
|
// 기본적인 구현만 제공하며, 필요에 따라 확장 가능합니다.
|
||||||
|
|
||||||
|
// 각 열린 3에 대해, 4를 만들 때 다른 쌍삼이 형성되는지 확인
|
||||||
|
foreach (var threeInfo in openThrees)
|
||||||
|
{
|
||||||
|
bool canFormFourWithoutChainDoubleThree = false;
|
||||||
|
|
||||||
|
foreach (var emptyPos in threeInfo.emptyPositions)
|
||||||
|
{
|
||||||
|
// 빈 위치에 돌을 놓았을 때
|
||||||
|
board[emptyPos.y, emptyPos.x] = Black;
|
||||||
|
|
||||||
|
// 다른 쌍삼이 형성되는지 확인 (연쇄 체크)
|
||||||
|
bool formsOtherDoubleThree = false;
|
||||||
|
|
||||||
|
// 다른 모든 빈 위치에 대해 쌍삼 체크
|
||||||
|
for (int r = 0; r < BoardSize; r++)
|
||||||
|
{
|
||||||
|
for (int c = 0; c < BoardSize; c++)
|
||||||
|
{
|
||||||
|
if (board[r, c] == Space)
|
||||||
|
{
|
||||||
|
// 임시로 돌 배치하여 쌍삼 체크
|
||||||
|
board[r, c] = Black;
|
||||||
|
bool isDoubleThree = CheckSimpleDoubleThree(board, r, c);
|
||||||
|
board[r, c] = Space;
|
||||||
|
|
||||||
|
if (isDoubleThree)
|
||||||
|
{
|
||||||
|
formsOtherDoubleThree = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (formsOtherDoubleThree) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 원래 상태로 복원
|
||||||
|
board[emptyPos.y, emptyPos.x] = Space;
|
||||||
|
|
||||||
|
// 연쇄 쌍삼이 형성되지 않으면 예외 조건 만족
|
||||||
|
if (!formsOtherDoubleThree)
|
||||||
|
{
|
||||||
|
canFormFourWithoutChainDoubleThree = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 하나의 삼이라도 연쇄 쌍삼 없이 4를 만들 수 있으면 예외 조건 만족
|
||||||
|
if (canFormFourWithoutChainDoubleThree)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 단순 쌍삼 체크 (연쇄 검사용, 재귀 호출 방지)
|
||||||
|
/// </summary>
|
||||||
|
private bool CheckSimpleDoubleThree(Enums.PlayerType[,] board, int row, int col)
|
||||||
|
{
|
||||||
|
int openThreeCount = 0;
|
||||||
|
|
||||||
|
// 4개의 방향 쌍에 대해 검사
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
int dir1 = DirectionPairs[i, 0];
|
||||||
|
int dir2 = DirectionPairs[i, 1];
|
||||||
|
|
||||||
|
// 간단한 열린 3 체크
|
||||||
|
if (CheckSimpleOpenThree(board, row, col, dir1, dir2))
|
||||||
|
{
|
||||||
|
openThreeCount++;
|
||||||
|
if (openThreeCount >= 2)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 단순 열린 3 체크 (연쇄 검사용)
|
||||||
|
/// </summary>
|
||||||
|
private bool CheckSimpleOpenThree(Enums.PlayerType[,] board, int row, int col, int dir1, int dir2)
|
||||||
|
{
|
||||||
|
Enums.PlayerType[] linePattern = ExtractLinePattern(board, row, col, dir1, dir2);
|
||||||
|
int centerIndex = 5;
|
||||||
|
|
||||||
|
// 연속된 열린 3 패턴 체크
|
||||||
|
for (int start = centerIndex - 2; start <= centerIndex; start++)
|
||||||
|
{
|
||||||
|
if (start < 0 || start + 2 >= linePattern.Length)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isConsecutiveThree = true;
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (linePattern[start + i] != Black)
|
||||||
|
{
|
||||||
|
isConsecutiveThree = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isConsecutiveThree)
|
||||||
|
{
|
||||||
|
bool isLeftOpen = (start - 1 >= 0) && (linePattern[start - 1] == Space);
|
||||||
|
bool isRightOpen = (start + 3 < linePattern.Length) && (linePattern[start + 3] == Space);
|
||||||
|
|
||||||
|
if (isLeftOpen && isRightOpen)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 한 칸 떨어진 열린 3 패턴 체크 (간단 구현)
|
||||||
|
for (int start = centerIndex - 3; start <= centerIndex; start++)
|
||||||
|
{
|
||||||
|
if (start < 0 || start + 3 >= linePattern.Length)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int stoneCount = 0;
|
||||||
|
int gapCount = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (linePattern[start + i] == Black)
|
||||||
|
{
|
||||||
|
stoneCount++;
|
||||||
|
}
|
||||||
|
else if (linePattern[start + i] == Space)
|
||||||
|
{
|
||||||
|
gapCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stoneCount = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stoneCount == 3 && gapCount == 1)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 쌍사 여부를 확인합니다 (예외 처리용)
|
||||||
|
/// </summary>
|
||||||
|
private bool CheckDoubleFour(Enums.PlayerType[,] board, int row, int col)
|
||||||
|
{
|
||||||
|
int fourCount = 0;
|
||||||
|
|
||||||
|
// 4개의 방향 쌍에 대해 검사
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
int dir1 = DirectionPairs[i, 0];
|
||||||
|
int dir2 = DirectionPairs[i, 1];
|
||||||
|
|
||||||
|
if (CheckFourInDirection(board, row, col, dir1, dir2))
|
||||||
|
{
|
||||||
|
fourCount++;
|
||||||
|
if (fourCount >= 2)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 특정 방향에서 4가 형성되는지 확인합니다.
|
||||||
|
/// </summary>
|
||||||
|
private bool CheckFourInDirection(Enums.PlayerType[,] board, int row, int col, int dir1, int dir2)
|
||||||
|
{
|
||||||
|
Enums.PlayerType[] linePattern = ExtractLinePattern(board, row, col, dir1, dir2);
|
||||||
|
int centerIndex = 5;
|
||||||
|
|
||||||
|
// 윈도우 슬라이딩으로 연속된 4를 검사
|
||||||
|
for (int start = 0; start <= 7; start++)
|
||||||
|
{
|
||||||
|
// 현재 위치가 이 윈도우에 포함되는지 확인
|
||||||
|
bool currentPositionInWindow = (start <= centerIndex && centerIndex < start + 4);
|
||||||
|
if (!currentPositionInWindow) continue;
|
||||||
|
|
||||||
|
// 윈도우 내의 돌 개수 세기
|
||||||
|
int stoneCount = 0;
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (linePattern[start + i] == Black)
|
||||||
|
{
|
||||||
|
stoneCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4개의 돌이 있으면 4로 판정
|
||||||
|
if (stoneCount == 4)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,11 +1,14 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
|
||||||
public class RenjuForbiddenMoveDetector
|
public class RenjuForbiddenMoveDetector : ForbiddenDetectorBase
|
||||||
{
|
{
|
||||||
// 렌주 룰 금수 감지기 생성
|
// 렌주 룰 금수 감지기 생성
|
||||||
private RenjuRuleChecker _ruleChecker = new RenjuRuleChecker();
|
private RenjuOverlineDetector _overlineDetactor = new();
|
||||||
|
private RenjuDoubleFourDetector _doubleFourDetactor = new();
|
||||||
|
private RenjuDoubleThreeDetector _doubleThreeDetector = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 렌주 룰로 금수 리스트를 반환하는 함수
|
/// 렌주 룰로 금수 리스트를 반환하는 함수
|
||||||
@ -14,6 +17,120 @@ public class RenjuForbiddenMoveDetector
|
|||||||
/// <returns>금수 좌표를 담은 리스트</returns>
|
/// <returns>금수 좌표를 담은 리스트</returns>
|
||||||
public List<Vector2Int> RenjuForbiddenMove(Enums.PlayerType[,] board)
|
public List<Vector2Int> RenjuForbiddenMove(Enums.PlayerType[,] board)
|
||||||
{
|
{
|
||||||
return _ruleChecker.GetForbiddenMoves(board);
|
|
||||||
|
var forbiddenCount = 0;
|
||||||
|
List<Vector2Int> forbiddenMoves = new();
|
||||||
|
List<Vector2Int> tempForbiddenMoves = new();
|
||||||
|
for (int row = 0; row < BoardSize; row++)
|
||||||
|
{
|
||||||
|
for (int col = 0; col < BoardSize; col++)
|
||||||
|
{
|
||||||
|
// ** 비어 있지 않으면 검사할 필요 없음 **
|
||||||
|
if (!IsEmptyPosition(board, row, col)) continue;
|
||||||
|
|
||||||
|
// 장목 검사
|
||||||
|
if (_overlineDetactor.IsOverline(board, row, col))
|
||||||
|
{
|
||||||
|
forbiddenCount++;
|
||||||
|
Debug.Log("장목 금수 좌표 X축 : " + row + ", Y축 : " + col);
|
||||||
|
forbiddenMoves.Add(new Vector2Int(row, col));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4-4 검사
|
||||||
|
if (_doubleFourDetactor.IsDoubleFour(board, row, col))
|
||||||
|
{
|
||||||
|
forbiddenCount++;
|
||||||
|
Debug.Log("사사 금수 좌표 X축 : " + row + ", Y축 : " + col);
|
||||||
|
forbiddenMoves.Add(new Vector2Int(row, col));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(forbiddenCount > 0) continue;
|
||||||
|
|
||||||
|
// 3-3 검사
|
||||||
|
if (_doubleThreeDetector.IsDoubleThree(board, row, col))
|
||||||
|
{
|
||||||
|
tempForbiddenMoves.Add(new Vector2Int(row, col));
|
||||||
|
// if (!SimulateDoubleFour(tempBoard))
|
||||||
|
// {
|
||||||
|
// Debug.Log("삼삼 금수 좌표 X축 : " + row + ", Y축 : " + col);
|
||||||
|
// forbiddenMoves.Add(new Vector2Int(row, col));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var pos in tempForbiddenMoves)
|
||||||
|
{
|
||||||
|
board[pos.x, pos.y] = Black;
|
||||||
|
if (!SimulateDoubleFour(board)&& !SimulateOverline(board))
|
||||||
|
{
|
||||||
|
Debug.Log("X: "+pos.x + "Y: "+ pos.y);
|
||||||
|
forbiddenMoves.Add(new Vector2Int(pos.x, pos.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Debug.Log(DebugBoard(board));
|
||||||
|
return forbiddenMoves;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
private bool SimulateDoubleFour(Enums.PlayerType[,] board)
|
||||||
|
{
|
||||||
|
for (int row = 0; row < BoardSize; row++)
|
||||||
|
{
|
||||||
|
for (int col = 0; col < BoardSize; col++)
|
||||||
|
{
|
||||||
|
if (_doubleFourDetactor.IsDoubleFour(board, row, col))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SimulateOverline(Enums.PlayerType[,] board)
|
||||||
|
{
|
||||||
|
for (int row = 0; row < BoardSize; row++)
|
||||||
|
{
|
||||||
|
for (int col = 0; col < BoardSize; col++)
|
||||||
|
{
|
||||||
|
if (_overlineDetactor.IsOverline(board, row, col))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 보드 상태를 시각적으로 출력하는 디버깅 함수
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="board">현재 보드 상태</param>
|
||||||
|
/// <returns>보드의 시각적 표현 문자열</returns>
|
||||||
|
private string DebugBoard(Enums.PlayerType[,] board)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
for (int row = 0; row < BoardSize; row++)
|
||||||
|
{
|
||||||
|
for (int col = 0; col < BoardSize; col++)
|
||||||
|
{
|
||||||
|
sb.Append(board[row, col] switch
|
||||||
|
{
|
||||||
|
Enums.PlayerType.None => "□",
|
||||||
|
Enums.PlayerType.PlayerA => "●",
|
||||||
|
Enums.PlayerType.PlayerB => "○",
|
||||||
|
_ => "?"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
sb.AppendLine(); // 줄바꿈 추가
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 8618553c3e244abdb040fb7378dd4b65
|
guid: 4440d621b56f2ce459d819497911892b
|
||||||
timeCreated: 1741939566
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 렌주 규칙의 모든 금수 규칙(3-3, 4-4, 장목)을 검사하는 통합 클래스
|
|
||||||
/// </summary>
|
|
||||||
public class RenjuRuleChecker: ForbiddenDetectorBase
|
|
||||||
{
|
|
||||||
private RenjuOverlineDetector _overlineDetactor = new();
|
|
||||||
private RenjuDoubleFourDetector _doubleFourDetactor = new();
|
|
||||||
private RenjuDoubleThreeDetector _doubleThreeDetector = new();
|
|
||||||
|
|
||||||
public List<Vector2Int> GetForbiddenMoves(Enums.PlayerType[,] board)
|
|
||||||
{
|
|
||||||
List<Vector2Int> forbiddenMoves = new();
|
|
||||||
for (int row = 0; row < BoardSize; row++)
|
|
||||||
{
|
|
||||||
for (int col = 0; col < BoardSize; col++)
|
|
||||||
{
|
|
||||||
// ** 비어 있지 않으면 검사할 필요 없음 **
|
|
||||||
if (!IsEmptyPosition(board, row, col)) continue;
|
|
||||||
|
|
||||||
// 장목 검사
|
|
||||||
if (_overlineDetactor.IsOverline(board, row, col))
|
|
||||||
{
|
|
||||||
Debug.Log("장목 금수 좌표 X축 : " + row + ", Y축 : " + col);
|
|
||||||
forbiddenMoves.Add(new Vector2Int(row, col));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4-4 검사
|
|
||||||
if (_doubleFourDetactor.IsDoubleFour(board, row, col))
|
|
||||||
{
|
|
||||||
Debug.Log("사사 금수 좌표 X축 : " + row + ", Y축 : " + col);
|
|
||||||
forbiddenMoves.Add(new Vector2Int(row, col));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3-3 검사
|
|
||||||
if (_doubleThreeDetector.IsDoubleThree(board, row, col))
|
|
||||||
{
|
|
||||||
Debug.Log("삼삼 금수 좌표 X축 : " + row + ", Y축 : " + col);
|
|
||||||
forbiddenMoves.Add(new Vector2Int(row, col));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return forbiddenMoves;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 083e8b9070ed407b8744d4cacd0d53dc
|
|
||||||
timeCreated: 1742256498
|
|
@ -13,7 +13,7 @@ public class ReplayController : MonoBehaviour
|
|||||||
[SerializeField] private GameObject[] userBProfileImages;
|
[SerializeField] private GameObject[] userBProfileImages;
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
InitReplayUI();
|
// InitReplayUI();
|
||||||
//TODO: 프로필 이미지 불러오기
|
//TODO: 프로필 이미지 불러오기
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,36 +25,13 @@ public class LeaderBoardController : MonoBehaviour
|
|||||||
if (isLeaderboardLoaded) return; // 이미 리더보드가 로드되었으면 중복 호출 방지
|
if (isLeaderboardLoaded) return; // 이미 리더보드가 로드되었으면 중복 호출 방지
|
||||||
|
|
||||||
leaderboardPanel.SetActive(true);
|
leaderboardPanel.SetActive(true);
|
||||||
StartCoroutine(GetLeaderboardData());
|
NetworkManager.Instance.GetLeaderboardData((leaderboardItems) =>
|
||||||
|
{
|
||||||
|
Show(leaderboardItems);
|
||||||
|
}, () => { });
|
||||||
isLeaderboardLoaded = true;
|
isLeaderboardLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator GetLeaderboardData()
|
|
||||||
{
|
|
||||||
string url = Constants.ServerURL + "/leaderboard"; // 서버의 리더보드 데이터 URL
|
|
||||||
|
|
||||||
UnityWebRequest www = UnityWebRequest.Get(url); // GET 요청으로 데이터 받기
|
|
||||||
yield return www.SendWebRequest(); // 요청 전송 대기
|
|
||||||
|
|
||||||
// 요청이 실패했을 때
|
|
||||||
if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError)
|
|
||||||
{
|
|
||||||
Debug.LogError("Error: " + www.error);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 성공적으로 데이터를 받아온 경우
|
|
||||||
string jsonResponse = www.downloadHandler.text; // 응답으로 받은 JSON 데이터
|
|
||||||
|
|
||||||
// JSON을 ScoreInfo 리스트로 파싱
|
|
||||||
ScoreListWrapper wrapper = JsonUtility.FromJson<ScoreListWrapper>(jsonResponse);
|
|
||||||
List<ScoreInfo> leaderboardItems = wrapper.scoreInfos;
|
|
||||||
|
|
||||||
// Show 메서드를 통해 데이터를 표시
|
|
||||||
Show(leaderboardItems);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Show(List<ScoreInfo> leaderboardItems)
|
public void Show(List<ScoreInfo> leaderboardItems)
|
||||||
{
|
{
|
||||||
// 기존 셀 삭제 (리스트가 갱신될 때마다)
|
// 기존 셀 삭제 (리스트가 갱신될 때마다)
|
||||||
@ -106,7 +83,7 @@ public class LeaderBoardController : MonoBehaviour
|
|||||||
if (!string.IsNullOrEmpty(savedData))
|
if (!string.IsNullOrEmpty(savedData))
|
||||||
{
|
{
|
||||||
// 저장된 JSON 데이터를 파싱하여 리더보드 리스트로 변환
|
// 저장된 JSON 데이터를 파싱하여 리더보드 리스트로 변환
|
||||||
leaderboard = JsonUtility.FromJson<ScoreListWrapper>(savedData).scoreInfos;
|
leaderboard = JsonUtility.FromJson<ScoreListWrapper>(savedData).leaderboardDatas;
|
||||||
}
|
}
|
||||||
|
|
||||||
return leaderboard;
|
return leaderboard;
|
||||||
|
@ -19,6 +19,7 @@ public class PanelManager : MonoBehaviour
|
|||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
|
SetCanvas();
|
||||||
// Prefabs 폴더에서 모든 패널 프리팹 로드
|
// Prefabs 폴더에서 모든 패널 프리팹 로드
|
||||||
GameObject[] prefabs = Resources.LoadAll<GameObject>("Prefabs/Panels");
|
GameObject[] prefabs = Resources.LoadAll<GameObject>("Prefabs/Panels");
|
||||||
|
|
||||||
@ -30,7 +31,7 @@ public class PanelManager : MonoBehaviour
|
|||||||
Debug.Log($"총 {panelPrefabs.Count}개의 패널이 로드됨.");
|
Debug.Log($"총 {panelPrefabs.Count}개의 패널이 로드됨.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Start()
|
void SetCanvas()
|
||||||
{
|
{
|
||||||
if (_canvas == null)
|
if (_canvas == null)
|
||||||
{
|
{
|
||||||
@ -114,7 +115,6 @@ public class PanelManager : MonoBehaviour
|
|||||||
if (_canvas != null)
|
if (_canvas != null)
|
||||||
{
|
{
|
||||||
var settingsPanelObject = GetPanel("Setting Panel");
|
var settingsPanelObject = GetPanel("Setting Panel");
|
||||||
settingsPanelObject.GetComponent<PanelController>().Show();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,9 +41,4 @@ public class ReplayPanelItemsController : ScrollPanelController
|
|||||||
replayCell.SetReplayRecord(replayRecord);
|
replayCell.SetReplayRecord(replayRecord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Show()
|
|
||||||
{
|
|
||||||
base.Show();
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -49,7 +49,7 @@ TextureImporter:
|
|||||||
alignment: 0
|
alignment: 0
|
||||||
spritePivot: {x: 0.5, y: 0.5}
|
spritePivot: {x: 0.5, y: 0.5}
|
||||||
spritePixelsToUnits: 100
|
spritePixelsToUnits: 100
|
||||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
spriteBorder: {x: 23, y: 21, z: 23, w: 22}
|
||||||
spriteGenerateFallbackPhysicsShape: 1
|
spriteGenerateFallbackPhysicsShape: 1
|
||||||
alphaUsage: 1
|
alphaUsage: 1
|
||||||
alphaIsTransparency: 1
|
alphaIsTransparency: 1
|
||||||
@ -126,7 +126,7 @@ TextureImporter:
|
|||||||
physicsShape: []
|
physicsShape: []
|
||||||
bones: []
|
bones: []
|
||||||
spriteID: 5e97eb03825dee720800000000000000
|
spriteID: 5e97eb03825dee720800000000000000
|
||||||
internalID: 0
|
internalID: 1537655665
|
||||||
vertices: []
|
vertices: []
|
||||||
indices:
|
indices:
|
||||||
edges: []
|
edges: []
|
||||||
|
@ -49,7 +49,7 @@ TextureImporter:
|
|||||||
alignment: 0
|
alignment: 0
|
||||||
spritePivot: {x: 0.5, y: 0.5}
|
spritePivot: {x: 0.5, y: 0.5}
|
||||||
spritePixelsToUnits: 100
|
spritePixelsToUnits: 100
|
||||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
spriteBorder: {x: 0, y: 19, z: 0, w: 20}
|
||||||
spriteGenerateFallbackPhysicsShape: 1
|
spriteGenerateFallbackPhysicsShape: 1
|
||||||
alphaUsage: 1
|
alphaUsage: 1
|
||||||
alphaIsTransparency: 1
|
alphaIsTransparency: 1
|
||||||
@ -126,7 +126,7 @@ TextureImporter:
|
|||||||
physicsShape: []
|
physicsShape: []
|
||||||
bones: []
|
bones: []
|
||||||
spriteID: 5e97eb03825dee720800000000000000
|
spriteID: 5e97eb03825dee720800000000000000
|
||||||
internalID: 0
|
internalID: 1537655665
|
||||||
vertices: []
|
vertices: []
|
||||||
indices:
|
indices:
|
||||||
edges: []
|
edges: []
|
||||||
|
@ -306,7 +306,11 @@ PrefabInstance:
|
|||||||
m_Modifications:
|
m_Modifications:
|
||||||
- target: {fileID: 626368541760032086, guid: 65aac0e22fe25aa42b9cf7df776a854d, type: 3}
|
- target: {fileID: 626368541760032086, guid: 65aac0e22fe25aa42b9cf7df776a854d, type: 3}
|
||||||
propertyPath: m_Name
|
propertyPath: m_Name
|
||||||
value: '[Canvas] Game UI'
|
value: Canvas
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 1250546304786973426, guid: 65aac0e22fe25aa42b9cf7df776a854d, type: 3}
|
||||||
|
propertyPath: m_AnchoredPosition.x
|
||||||
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 6113787613246818512, guid: 65aac0e22fe25aa42b9cf7df776a854d, type: 3}
|
- target: {fileID: 6113787613246818512, guid: 65aac0e22fe25aa42b9cf7df776a854d, type: 3}
|
||||||
propertyPath: m_Pivot.x
|
propertyPath: m_Pivot.x
|
||||||
@ -21706,6 +21710,7 @@ GameObject:
|
|||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 1260188604546925059}
|
- component: {fileID: 1260188604546925059}
|
||||||
- component: {fileID: 5677811662396631252}
|
- component: {fileID: 5677811662396631252}
|
||||||
|
- component: {fileID: 5677811662396631253}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: GameManager
|
m_Name: GameManager
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@ -33884,10 +33889,104 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 35a4c6d5d3a97b444b968e68ec8bb9f7, type: 3}
|
m_Script: {fileID: 11500000, guid: 35a4c6d5d3a97b444b968e68ec8bb9f7, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
signinPanel: {fileID: 0}
|
panelManagerPrefab: {fileID: 3475740041361426276, guid: 085ca07ca90c92545b2594bd13412701, type: 3}
|
||||||
signupPanel: {fileID: 0}
|
audioManagerPrefab: {fileID: 2946408323859178723, guid: e829818dce39a5d4383e061111bed871, type: 3}
|
||||||
canvas: {fileID: 0}
|
--- !u!82 &5677811662396631253
|
||||||
profileSprites: []
|
AudioSource:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 3626119060319719757}
|
||||||
|
m_Enabled: 1
|
||||||
|
serializedVersion: 4
|
||||||
|
OutputAudioMixerGroup: {fileID: 0}
|
||||||
|
m_audioClip: {fileID: 0}
|
||||||
|
m_PlayOnAwake: 1
|
||||||
|
m_Volume: 1
|
||||||
|
m_Pitch: 1
|
||||||
|
Loop: 0
|
||||||
|
Mute: 0
|
||||||
|
Spatialize: 0
|
||||||
|
SpatializePostEffects: 0
|
||||||
|
Priority: 128
|
||||||
|
DopplerLevel: 1
|
||||||
|
MinDistance: 1
|
||||||
|
MaxDistance: 500
|
||||||
|
Pan2D: 0
|
||||||
|
rolloffMode: 0
|
||||||
|
BypassEffects: 0
|
||||||
|
BypassListenerEffects: 0
|
||||||
|
BypassReverbZones: 0
|
||||||
|
rolloffCustomCurve:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Curve:
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 0
|
||||||
|
value: 1
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0.33333334
|
||||||
|
outWeight: 0.33333334
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 1
|
||||||
|
value: 0
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0.33333334
|
||||||
|
outWeight: 0.33333334
|
||||||
|
m_PreInfinity: 2
|
||||||
|
m_PostInfinity: 2
|
||||||
|
m_RotationOrder: 4
|
||||||
|
panLevelCustomCurve:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Curve:
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 0
|
||||||
|
value: 0
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0.33333334
|
||||||
|
outWeight: 0.33333334
|
||||||
|
m_PreInfinity: 2
|
||||||
|
m_PostInfinity: 2
|
||||||
|
m_RotationOrder: 4
|
||||||
|
spreadCustomCurve:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Curve:
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 0
|
||||||
|
value: 0
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0.33333334
|
||||||
|
outWeight: 0.33333334
|
||||||
|
m_PreInfinity: 2
|
||||||
|
m_PostInfinity: 2
|
||||||
|
m_RotationOrder: 4
|
||||||
|
reverbZoneMixCustomCurve:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Curve:
|
||||||
|
- serializedVersion: 3
|
||||||
|
time: 0
|
||||||
|
value: 1
|
||||||
|
inSlope: 0
|
||||||
|
outSlope: 0
|
||||||
|
tangentMode: 0
|
||||||
|
weightedMode: 0
|
||||||
|
inWeight: 0.33333334
|
||||||
|
outWeight: 0.33333334
|
||||||
|
m_PreInfinity: 2
|
||||||
|
m_PostInfinity: 2
|
||||||
|
m_RotationOrder: 4
|
||||||
--- !u!61 &5684907091474785187
|
--- !u!61 &5684907091474785187
|
||||||
BoxCollider2D:
|
BoxCollider2D:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user