元宵快樂


博客園的小伙伴們,新年好啊。

春節剛過,元宵又至。不知大家所在之處是否還有看花燈,猜燈謎的傳統呢?應此情此景,我們依托微軟亞洲研究院自然語言計算組的研究成果,為大家帶來了UAP版本的微軟字謎APP:

Windows Phone Store地址 : 微軟字謎

就算沒有時間去看燈,也可以在手機上體驗一把文藝范。

在微軟字謎中,你可以闖過323關,一展聰明才智;可以用APP幫你出字謎給小伙伴猜,讓他們也死幾個腦細胞;還能上傳原創字謎,與大家同樂。

與之前一樣,接下來和大家分享下開發中的有意思的地方:

主頁

主頁沿用了微軟對聯的形式,加入了3個小動畫:

燈籠翻轉:

<Storyboard x:Name="sb_LanternRotate" Completed="sb_LanternRotate_Completed">

<DoubleAnimation Storyboard.TargetName="img_Lantern" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)"

From="0" To="360" Duration="0:0:1"/>

<DoubleAnimation Storyboard.TargetName="img_Lantern" Storyboard.TargetProperty="Opacity"

From="0" To="1" Duration="0:0:1"/>

</Storyboard>

菜單轉動:

<Storyboard x:Name="sb_Menu" Completed="sb_Menu_Completed">

<DoubleAnimation Storyboard.TargetName="menu_Guess" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)"

From="90" To="0" Duration="0:0:0.20" BeginTime="0:0:0.20"/>

<DoubleAnimation Storyboard.TargetName="menu_Produce" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)"

From="90" To="0" Duration="0:0:0.20" BeginTime="0:0:0.40"/>

<DoubleAnimation Storyboard.TargetName="menu_Intro" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)"

From="90" To="0" Duration="0:0:0.20" BeginTime="0:0:0.60"/>

<DoubleAnimation Storyboard.TargetName="menu_My" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)"

From="90" To="0" Duration="0:0:0.20" BeginTime="0:0:0.60"/>

<DoubleAnimation Storyboard.TargetName="menu_Cloud" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)"

From="90" To="0" Duration="0:0:0.20" BeginTime="0:0:0.80"/>

</Storyboard>

燈籠移動:

<Storyboard x:Name="sb_LanternMove" Completed="sb_LanternMove_Completed">

<DoubleAnimation Storyboard.TargetName="img_Lantern" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)"

From="1" To="0.9" Duration="0:0:1"/>

<DoubleAnimation Storyboard.TargetName="img_Lantern" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)"

From="1" To="0.9" Duration="0:0:1"/>

<DoubleAnimation Storyboard.TargetName="img_Lantern" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)"

From="0" To="150" Duration="0:0:1"/>

<DoubleAnimation Storyboard.TargetName="img_Lantern" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"

From="0" To="-10" Duration="0:0:1"/>

 

</Storyboard>

關於飛入:

<Storyboard x:Name="sb_About">

<DoubleAnimation Storyboard.TargetName="tb_About" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"

From="50" To="0" Duration="0:0:1"/>

<DoubleAnimation Storyboard.TargetName="tb_About" Storyboard.TargetProperty="Opacity"

From="0" To="1" Duration="0:0:1"/>

</Storyboard>

然后利用 storyboard的 Completed 事件來將它們連貫起來:

protected async override void OnNavigatedTo(NavigationEventArgs e)

{

if (e.NavigationMode == NavigationMode.New)

{

Logger.LogAgent.GetInstance().WriteLog(this.GetType().FullName);

 

this.isBack = false;

await Windows.UI.ViewManagement.StatusBar.GetForCurrentView().HideAsync();

this.sb_LanternRotate.Begin();

}

else

{

this.isBack = true;

this.sb_Menu.Begin();

}

}

private void sb_LanternRotate_Completed(object sender, object e)

{

this.sb_Menu.Begin();

}

 

private void sb_Menu_Completed(object sender, object e)

{

if (!this.isBack)

{

this.sb_LanternMove.Begin();

}

}

private void sb_LanternMove_Completed(object sender, object e)

{

this.sb_About.Begin();

}

要注意的就是在OnNavigatedFrom中,需要把再次進入頁面時還會移動的動畫元素歸位:

this.menu_Guess.Projection.SetValue(PlaneProjection.RotationXProperty, 90);

this.menu_Produce.Projection.SetValue(PlaneProjection.RotationXProperty, 90);

this.menu_Intro.Projection.SetValue(PlaneProjection.RotationXProperty, 90);

this.menu_My.Projection.SetValue(PlaneProjection.RotationXProperty, 90);

this.menu_Cloud.Projection.SetValue(PlaneProjection.RotationXProperty, 90);

另外就是雙擊完全退出APP的功能:

我們在頁面上添加一個默認隱藏的提示:

<Border x:Name="bd_QuitInfo" Background="#FFC40E12" Visibility="Collapsed" Opacity="0.75" CornerRadius="10" Canvas.ZIndex="99" HorizontalAlignment="Center" VerticalAlignment="Center" BorderThickness="5" BorderBrush="Gold" Margin="0,200,50,0">

<TextBlock Style="{StaticResource RiddleGoldMessage}" HorizontalAlignment="Center" Foreground="White" Margin="20,10">

<Run Text="再按一次"/>

<LineBreak/>

<Run Text="退出應用"/>

</TextBlock>

</Border>

然后handle一下后退按鈕按下的事件:

在OnNavigatedTo中添加:

Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;

在OnNavigatedFrom中添加:

Windows.Phone.UI.Input.HardwareButtons.BackPressed -= HardwareButtons_BackPressed;

最后添加HardwareButtons_BackPressed事件處理方法:

DateTime _lastTimeClickBack = DateTime.MinValue;

bool isQuitInfoOpen = false;

 

void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)

{

var deltaTime = DateTime.Now - _lastTimeClickBack;

 

// double click back button within 3 seconds

if (!isQuitInfoOpen)

{

this.menu_Guess.Projection.SetValue(PlaneProjection.RotationXProperty, 90);

this.menu_Produce.Projection.SetValue(PlaneProjection.RotationXProperty, 90);

this.menu_Intro.Projection.SetValue(PlaneProjection.RotationXProperty, 90);

this.menu_My.Projection.SetValue(PlaneProjection.RotationXProperty, 90);

this.menu_Cloud.Projection.SetValue(PlaneProjection.RotationXProperty, 90);

 

 

_lastTimeClickBack = DateTime.Now;

this.bd_QuitInfo.Visibility = Windows.UI.Xaml.Visibility.Visible;

isQuitInfoOpen = true;

 

// close the tip within 3 seconds

ThreadPoolTimer.CreateTimer(async t =>

{

await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>

{

this.bd_QuitInfo.Visibility = Windows.UI.Xaml.Visibility.Collapsed;

isQuitInfoOpen = false;

this.isBack = true;

this.sb_Menu.Begin();

});

}, new TimeSpan(0, 0, 3));

e.Handled = true;

}

else

{

//double click back button in 5 seconds to exit

if (deltaTime.TotalSeconds < 5)

{

Application.Current.Exit();

}

e.Handled = true;

}

猜字謎

我們精選了323個不同長度的,由微軟亞洲研究院自然語言計算組研發的計算機自動猜字和出字謎系統生成的字謎。每猜出一個都可以得到最多10分,大家可以上傳自己的分數,總分排名在前20的小伙伴就能出現在APP內的排行榜上哦。

猜字謎的部分比較重要,為了趕在元宵之前能夠上線,我們的pm兼dev Xiaowu 同志犧牲春節假期實現了這一重要功能:

思路大致是這樣的:

我們自定義了2種模板控件,CandidateControl 作為候選字控件,每個都顯示一個字; CandidateArrayControl 則作為容器處理候選字的交互。

當我們進入猜謎頁面,為了大家不至於覺得無從猜起,APP會生成18個候選字的列表,正確答案就藏在其中。

接着將列表綁定到容器的datacontext,再通過容器的DataContextChanged事件,把候選字綁定到對應的候選字控件。

當我們點擊候選字控件,就將對應的候選字顯示謎底位置,並在容器中隱藏對應的候選字控件。

如果答對,則會播放一個小動畫,還有音效。

如果答錯3次,那候選字列表就會大換血,所以亂點也是不大容易蒙對的。

另外還可以犧牲一點分數來減少干擾項。

出字謎

出字謎則比較簡單了。

我們可以寫一個1~4個字的謎底,比如"我愛你",一段提示猜什么的謎目比如"打一句話",點擊下一步。

APP就會把我們的謎底上傳到雲端的字謎系統,取得謎底每個字的候選謎面顯示出來。

我們選好謎面(不滿意字謎系統給出的話還可以自行修改),就可以給小伙伴(或者心上人)去猜啦。要是覺得不錯,可以點擊收藏,把謎語保存到我的字謎中,供以后使用或者分享。

分享字謎

在可以猜字謎的頁面上,都可以分享或者求助。具體實現可以參照我們之前的博文 博客園客戶端UAP開發隨筆 -- 讓自己的App連接世界:WinRT中的微博分享博客園客戶端UAP開發隨筆讓自己的App連接世界(2)WinRT中的內置分享

另外我們還提供了分享到雲端字謎的功能。

雲端字謎

雲端字謎都是小伙伴們分享上來的字謎,而且答對也能加分哦。想在排行榜上秀出來,就靠它了。

好吧,就寫到這里,大家有意見歡迎拍過來啊。

我們的APP鏈接:微軟字謎

MSRA的網頁版字謎:微軟字謎(在線)

最后祝大家元宵節快樂~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM